diff --git a/evm/src/cpu/kernel/asm/core/jumpdest_analysis.asm b/evm/src/cpu/kernel/asm/core/jumpdest_analysis.asm index 56d9e126..bda6f96e 100644 --- a/evm/src/cpu/kernel/asm/core/jumpdest_analysis.asm +++ b/evm/src/cpu/kernel/asm/core/jumpdest_analysis.asm @@ -4,9 +4,8 @@ global jumpdest_analysis: // stack: ctx, code_len, retdest PUSH 0 // i = 0 - %stack (i, ctx, code_len, retdest) -> (i, ctx, code_len, retdest, 0) // ctr -global loop: +loop: // stack: i, ctx, code_len, retdest // Ideally we would break if i >= code_len, but checking i > code_len is // cheaper. It doesn't hurt to over-read by 1, since we'll read 0 which is @@ -14,20 +13,6 @@ global loop: DUP3 DUP2 GT // i > code_len %jumpi(return) - %stack (i, ctx) -> (ctx, @SEGMENT_CODE, i, 32, i, ctx) - %mload_packing - // stack: packed_opcodes - DUP1 - PUSH 0x8080808080808080808080808080808080808080808080808080808080808080 - AND -global debug_before_as_dad: - %jumpi(as_dad) -global debug_wuau: -as_dad: - POP -global debug_not_wuau: - - // stack: i, ctx, code_len, retdest %stack (i, ctx) -> (ctx, @SEGMENT_CODE, i, i, ctx) MLOAD_GENERAL @@ -43,11 +28,8 @@ global debug_not_wuau: // stack: JUMPDEST, i, ctx, code_len, retdest %stack (JUMPDEST, i, ctx) -> (1, ctx, @SEGMENT_JUMPDEST_BITS, i, JUMPDEST, i, ctx) MSTORE_GENERAL - %stack (opcode, i, ctx, code_len, retdest, ctr) -> (ctr, opcode, i, ctx, code_len, retdest) - %increment - %stack (ctr, opcode, i, ctx, code_len, retdest) -> (opcode, i, ctx, code_len, retdest, ctr) -global continue: +continue: // stack: opcode, i, ctx, code_len, retdest %add_const(code_bytes_to_skip) %mload_kernel_code @@ -56,12 +38,9 @@ global continue: // stack: i, ctx, code_len, retdest %jump(loop) -global return: +return: // stack: i, ctx, code_len, retdest %pop3 - SWAP1 -global debug_ctr: - POP JUMP // Determines how many bytes away is the next opcode, based on the opcode we read. @@ -69,7 +48,7 @@ global debug_ctr: // // Note that the range of PUSH opcodes is [0x60, 0x80). I.e. PUSH1 is 0x60 // and PUSH32 is 0x7f. -global code_bytes_to_skip: +code_bytes_to_skip: %rep 96 BYTES 1 // 0x00-0x5f %endrep diff --git a/evm/src/cpu/kernel/asm/main.asm b/evm/src/cpu/kernel/asm/main.asm index f6cd03bc..d1e06b66 100644 --- a/evm/src/cpu/kernel/asm/main.asm +++ b/evm/src/cpu/kernel/asm/main.asm @@ -13,6 +13,8 @@ global main: // Initialise the shift table %shift_table_init + // Encode constant nodes + %initialize_rlp_segment // Encode constant nodes %initialize_rlp_segment diff --git a/evm/src/cpu/kernel/asm/mpt/hash/hash.asm b/evm/src/cpu/kernel/asm/mpt/hash/hash.asm index 3bbb84f3..cf0634fd 100644 --- a/evm/src/cpu/kernel/asm/mpt/hash/hash.asm +++ b/evm/src/cpu/kernel/asm/mpt/hash/hash.asm @@ -49,10 +49,9 @@ mpt_hash_hash_rlp_after_unpacking: // The result is given as a (value, length) pair, where the length is given // in bytes. // -// Pre stack: node_ptr, encode_value, retdest -// Post stack: result, result_len +// Pre stack: node_ptr, encode_value, cur_len, retdest +// Post stack: result, result_len, cur_len global encode_or_hash_node: - // stack: node_ptr, encode_value, cur_len, retdest DUP1 %mload_trie_data // Check if we're dealing with a concrete node, i.e. not a hash node. @@ -92,11 +91,11 @@ maybe_hash_node: KECCAK_GENERAL %stack (hash, cur_len, retdest) -> (retdest, hash, 32, cur_len) JUMP -global pack_small_rlp: - // stack: result_ptr, result_len, retdest +pack_small_rlp: + // stack: result_ptr, result_len, cur_len, retdest %stack (result_ptr, result_len) -> (0, @SEGMENT_RLP_RAW, result_ptr, result_len, - after_packed_small_rlp, result_len, cur_len) + after_packed_small_rlp, result_len) %jump(mload_packing) after_packed_small_rlp: %stack (result, result_len, cur_len, retdest) -> (retdest, result, result_len, cur_len) @@ -105,10 +104,10 @@ after_packed_small_rlp: // RLP encode the given trie node, and return an (pointer, length) pair // indicating where the data lives within @SEGMENT_RLP_RAW. // -// Pre stack: node_type, node_ptr, encode_value, retdest +// Pre stack: node_type, node_ptr, encode_value, cur_len, retdest // Post stack: result_ptr, result_len -global encode_node: - // stack: node_type, node_ptr, encode_value, retdest +encode_node: + // stack: node_type, node_ptr, encode_value, cur_len, retdest // Increment node_ptr, so it points to the node payload instead of its type. SWAP1 %increment SWAP1 // stack: node_type, node_payload_ptr, encode_value, cur_len, retdest @@ -122,14 +121,16 @@ global encode_node: // been handled earlier in encode_or_hash_node, or something invalid. PANIC +global encode_node_empty: + // stack: node_type, node_payload_ptr, encode_value, cur_len, retdest + %pop3 + %stack (cur_len, retdest) -> (retdest, @ENCODED_EMPTY_NODE_POS, 1, cur_len) + JUMP + global encode_node_empty: // stack: node_type, node_payload_ptr, encode_value, retdest %pop3 - PUSH 0x1000 - %mload_kernel(@SEGMENT_RLP_RAW) -global debug_it_should_be_128: - POP - %stack (retdest) -> (retdest, 0x1000, 1) + %stack (retdest) -> (retdest, @ENCODED_EMPTY_NODE_POS, 1) JUMP global encode_node_branch: @@ -140,33 +141,19 @@ global encode_node_branch: SWAP2 %add_const(18) SWAP2 // stack: node_payload_ptr, encode_value, cur_len, retdest - // Get the next unused offset within the encoded child buffers. - // Then immediately increment the next unused offset by 16, so any - // recursive calls will use nonoverlapping offsets. - // TODO: Allocate a block of RLP memory instead? - %mload_global_metadata(@GLOBAL_METADATA_TRIE_ENCODED_CHILD_SIZE) - DUP1 %add_const(16) - %mstore_global_metadata(@GLOBAL_METADATA_TRIE_ENCODED_CHILD_SIZE) - // stack: base_offset, node_payload_ptr, encode_value, cur_len, retdest - // We will call encode_or_hash_node on each child. For the i'th child, we - // will store the result in SEGMENT_TRIE_ENCODED_CHILD[base + i], and its length in - // SEGMENT_TRIE_ENCODED_CHILD_LEN[base + i]. + // Allocate a block of RLP memory + %alloc_rlp_block DUP1 + // stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len retdest + + // Call encode_or_hash_node on each child %encode_child(0) %encode_child(1) %encode_child(2) %encode_child(3) %encode_child(4) %encode_child(5) %encode_child(6) %encode_child(7) %encode_child(8) %encode_child(9) %encode_child(10) %encode_child(11) %encode_child(12) %encode_child(13) %encode_child(14) %encode_child(15) - // stack: base_offset, node_payload_ptr, encode_value, cur_len, retdest - // Now, append each child to our RLP tape. - %alloc_rlp_block DUP1 - // stack: rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest - %append_child(0) %append_child(1) %append_child(2) %append_child(3) - %append_child(4) %append_child(5) %append_child(6) %append_child(7) - %append_child(8) %append_child(9) %append_child(10) %append_child(11) - %append_child(12) %append_child(13) %append_child(14) %append_child(15) - // stack: rlp_pos', rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest + // stack: rlp_pos', rlp_start, node_payload_ptr, encode_value, cur_len, retdest - %stack (rlp_pos, rlp_start, base_offset, node_payload_ptr) + %stack (rlp_pos, rlp_start, node_payload_ptr) -> (node_payload_ptr, rlp_pos, rlp_start) %add_const(16) // stack: value_ptr_ptr, rlp_pos', rlp_start, encode_value, cur_len, retdest @@ -198,48 +185,36 @@ encode_node_branch_prepend_prefix: -> (retdest, rlp_prefix_start, rlp_len, cur_len) JUMP + // Part of the encode_node_branch function. Encodes the i'th child. -// Stores the result in SEGMENT_TRIE_ENCODED_CHILD[base + i], and its length in -// SEGMENT_TRIE_ENCODED_CHILD_LEN[base + i]. %macro encode_child(i) - // stack: base_offset, node_payload_ptr, encode_value, cur_len, retdest + // stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest PUSH %%after_encode - DUP4 DUP4 - // stack: node_payload_ptr, encode_value, %%after_encode, base_offset, node_payload_ptr, encode_value, cur_len, retdest + DUP6 DUP6 DUP6 + // stack: node_payload_ptr, encode_value, cur_len, %%after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest %add_const($i) %mload_trie_data - // stack: child_i_ptr, encode_value, %%after_encode, base_offset, node_payload_ptr, encode_value, cur_len, retdest - %stack(child_i_ptr, encode_value, after_encode, base_offset, node_payload_ptr, encode_value, cur_len) -> (child_i_ptr, encode_value, cur_len, after_encode, base_offset, node_payload_ptr, encode_value) + // stack: child_i_ptr, encode_value, cur_len, %%after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest + %stack + (child_i_ptr, encode_value, cur_len, after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest) -> + (child_i_ptr, encode_value, cur_len, after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest) %jump(encode_or_hash_node) %%after_encode: - // stack: result, result_len, cur_len, base_offset, node_payload_ptr, encode_value, retdest - %stack(result, result_len, cur_len, base_offset, node_payload_ptr, encode_value) -> (result, result_len, base_offset, node_payload_ptr, encode_value, cur_len) - DUP3 %add_const($i) %mstore_kernel(@SEGMENT_TRIE_ENCODED_CHILD) - // stack: result_len, base_offset, node_payload_ptr, encode_value, cur_len, retdest - DUP2 %add_const($i) %mstore_kernel(@SEGMENT_TRIE_ENCODED_CHILD_LEN) - // stack: base_offset, node_payload_ptr, encode_value, cur_len, retdest -%endmacro - -// Part of the encode_node_branch function. Appends the i'th child's RLP. -%macro append_child(i) - // stack: rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest - DUP3 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD) // load result - DUP4 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD_LEN) // load result_len - // stack: result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest + // stack: result, result_len, cur_len, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest // If result_len != 32, result is raw RLP, with an appropriate RLP prefix already. - DUP1 %sub_const(32) %jumpi(%%unpack) + SWAP1 DUP1 %sub_const(32) %jumpi(%%unpack) // Otherwise, result is a hash, and we need to add the prefix 0x80 + 32 = 160. - // stack: result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest + // stack: result_len, result, cur_len, rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest PUSH 160 - DUP4 // rlp_pos + DUP5 // rlp_pos %mstore_rlp - SWAP2 %increment SWAP2 // rlp_pos += 1 + SWAP3 %increment SWAP3 // rlp_pos += 1 %%unpack: - %stack (result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest) + %stack (result_len, result, cur_len, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest) -> (rlp_pos, result, result_len, %%after_unpacking, - rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest) + rlp_start, node_payload_ptr, encode_value, cur_len, retdest) %jump(mstore_unpacking_rlp) %%after_unpacking: - // stack: rlp_pos', rlp_start, base_offset, node_payload_ptr, encode_value, cur_len, retdest + // stack: rlp_pos', rlp_start, node_payload_ptr, encode_value, cur_len, retdest %endmacro global encode_node_extension: @@ -322,81 +297,3 @@ encode_node_leaf_after_encode_value: %stack (rlp_prefix_start_pos, rlp_len, cur_len, retdest) -> (retdest, rlp_prefix_start_pos, rlp_len, cur_len) JUMP - -global encode_node_branch_new: - // stack: node_type, node_payload_ptr, encode_value, retdest - POP - // stack: node_payload_ptr, encode_value, retdest - - //Allocate a block of RLP memory - %alloc_rlp_block DUP1 - // stack: rlp_pos, node_payload_ptr, encode_value, retdest - - // Call encode_or_hash_node on each child - %encode_child_new(0) %encode_child_new(1) %encode_child_new(2) %encode_child_new(3) - %encode_child_new(4) %encode_child_new(5) %encode_child_new(6) %encode_child_new(7) - %encode_child_new(8) %encode_child_new(9) %encode_child_new(10) %encode_child_new(11) - %encode_child_new(12) %encode_child_new(13) %encode_child_new(14) %encode_child_new(15) - - // stack: rlp_pos', rlp_start, node_payload_ptr, encode_value, retdest - - %stack (rlp_pos, rlp_start, node_payload_ptr) - -> (node_payload_ptr, rlp_pos, rlp_start) - %add_const(16) - // stack: value_ptr_ptr, rlp_pos', rlp_start, encode_value, retdest - %mload_trie_data - // stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest - DUP1 %jumpi(encode_node_branch_with_value_new) - - // No value; append the empty string (0x80). - // stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest - %stack (value_ptr, rlp_pos, rlp_start, encode_value) -> (rlp_pos, 0x80, rlp_pos, rlp_start) - %mstore_rlp - // stack: rlp_pos', rlp_start, retdest - %increment - // stack: rlp_pos'', rlp_start, retdest - %jump(encode_node_branch_prepend_prefix_new) -encode_node_branch_with_value_new: - // stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest - %stack (value_ptr, rlp_pos, rlp_start, encode_value) - -> (encode_value, rlp_pos, value_ptr, encode_node_branch_prepend_prefix, rlp_start) - JUMP // call encode_value -encode_node_branch_prepend_prefix_new: - // stack: rlp_pos'', rlp_start, retdest - %prepend_rlp_list_prefix - // stack: rlp_prefix_start, rlp_len, retdest - %stack (rlp_prefix_start, rlp_len, retdest) - -> (retdest, rlp_prefix_start, rlp_len) - JUMP - - -// Part of the encode_node_branch function. Encodes the i'th child. -// Stores the result in SEGMENT_TRIE_ENCODED_CHILD[base + i], and its length in -// SEGMENT_TRIE_ENCODED_CHILD_LEN[base + i]. -%macro encode_child_new(i) - // stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest - PUSH %%after_encode - DUP5 DUP5 - // stack: node_payload_ptr, encode_value, %%after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest - %add_const($i) %mload_trie_data - // stack: child_i_ptr, encode_value, %%after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest - %jump(encode_or_hash_node) -%%after_encode: - // stack: result, result_len, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest - // If result_len != 32, result is raw RLP, with an appropriate RLP prefix already. - SWAP1 DUP1 %sub_const(32) %jumpi(%%unpack) - // Otherwise, result is a hash, and we need to add the prefix 0x80 + 32 = 160. - // stack: result_len, result, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest - PUSH 160 - DUP4 // rlp_pos - %mstore_rlp - SWAP2 %increment SWAP2 // rlp_pos += 1 -%%unpack: - %stack (result_len, result, rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest) - -> (rlp_pos, result, result_len, %%after_unpacking, - rlp_start, node_payload_ptr, encode_value, retdest) - %jump(mstore_unpacking_rlp) -%%after_unpacking: - // stack: rlp_pos', rlp_start, node_payload_ptr, encode_value, retdest -%endmacro - diff --git a/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm index 2ffefb7d..f3ee000d 100644 --- a/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm @@ -3,6 +3,9 @@ global mpt_hash_state_trie: // stack: cur_len, retdest PUSH encode_account + PUSH debug_before_encoding_child + PUSH mpt_delete + %pop2 %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) // stack: node_ptr, encode_account, cur_len, retdest %jump(mpt_hash) @@ -101,6 +104,10 @@ global encode_account: DUP3 %add_const(2) %mload_trie_data // storage_root_ptr = value[2] // stack: storage_root_ptr, cur_len, rlp_pos_5, value_ptr, cur_len, retdest + + PUSH debug_after_hash_storage_trie + POP + // Hash storage trie. %mpt_hash_storage_trie // stack: storage_root_digest, new_len, rlp_pos_5, value_ptr, cur_len, retdest diff --git a/evm/src/cpu/kernel/asm/mpt/util.asm b/evm/src/cpu/kernel/asm/mpt/util.asm index b492a0d0..27418b17 100644 --- a/evm/src/cpu/kernel/asm/mpt/util.asm +++ b/evm/src/cpu/kernel/asm/mpt/util.asm @@ -11,13 +11,9 @@ %endmacro %macro initialize_rlp_segment - // Write the encoding of the empty node to address 0 leaving 9 bytes for a prefix - // TODO: Do we need a prefix? PUSH 0x80 - PUSH 0x1000 + PUSH @ENCODED_EMPTY_NODE_POS %mstore_rlp - PUSH 0x1000 // TODO: use 10? - %mstore_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) %endmacro %macro alloc_rlp_block @@ -27,7 +23,7 @@ // In our model it's fine to use memory in a sparse way, as long as the gaps aren't larger than // 2^16 or so. So instead of the caller specifying the size of the block they need, we'll just // allocate 0x10000 = 2^16 bytes, much larger than any RLP blob the EVM could possibly create. - DUP1 %add_const(0x10000) + DUP1 %add_const(@MAX_RLP_BLOB_SIZE) // stack: block_end, block_start %mstore_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) // stack: block_start diff --git a/evm/src/cpu/kernel/constants/global_metadata.rs b/evm/src/cpu/kernel/constants/global_metadata.rs index 8b85c0b5..b5e52e5c 100644 --- a/evm/src/cpu/kernel/constants/global_metadata.rs +++ b/evm/src/cpu/kernel/constants/global_metadata.rs @@ -30,68 +30,64 @@ pub(crate) enum GlobalMetadata { TransactionTrieRootDigestAfter = 11, ReceiptTrieRootDigestAfter = 12, - /// The sizes of the `TrieEncodedChild` and `TrieEncodedChildLen` buffers. In other words, the - /// next available offset in these buffers. - TrieEncodedChildSize = 13, - // Block metadata. - BlockBeneficiary = 14, - BlockTimestamp = 15, - BlockNumber = 16, - BlockDifficulty = 17, - BlockRandom = 18, - BlockGasLimit = 19, - BlockChainId = 20, - BlockBaseFee = 21, - BlockGasUsed = 22, + BlockBeneficiary = 13, + BlockTimestamp = 14, + BlockNumber = 15, + BlockDifficulty = 16, + BlockRandom = 17, + BlockGasLimit = 18, + BlockChainId = 19, + BlockBaseFee = 20, + BlockGasUsed = 21, /// Before current transactions block values. - BlockGasUsedBefore = 23, + BlockGasUsedBefore = 22, /// After current transactions block values. - BlockGasUsedAfter = 24, + BlockGasUsedAfter = 23, /// Current block header hash - BlockCurrentHash = 25, + BlockCurrentHash = 24, /// Gas to refund at the end of the transaction. - RefundCounter = 26, + RefundCounter = 25, /// Length of the addresses access list. - AccessedAddressesLen = 27, + AccessedAddressesLen = 26, /// Length of the storage keys access list. - AccessedStorageKeysLen = 28, + AccessedStorageKeysLen = 27, /// Length of the self-destruct list. - SelfDestructListLen = 29, + SelfDestructListLen = 28, /// Length of the bloom entry buffer. - BloomEntryLen = 30, + BloomEntryLen = 29, /// Length of the journal. - JournalLen = 31, + JournalLen = 30, /// Length of the `JournalData` segment. - JournalDataLen = 32, + JournalDataLen = 31, /// Current checkpoint. - CurrentCheckpoint = 33, - TouchedAddressesLen = 34, + CurrentCheckpoint = 32, + TouchedAddressesLen = 33, // Gas cost for the access list in type-1 txns. See EIP-2930. - AccessListDataCost = 35, + AccessListDataCost = 34, // Start of the access list in the RLP for type-1 txns. - AccessListRlpStart = 36, + AccessListRlpStart = 35, // Length of the access list in the RLP for type-1 txns. - AccessListRlpLen = 37, + AccessListRlpLen = 36, // Boolean flag indicating if the txn is a contract creation txn. - ContractCreation = 38, - IsPrecompileFromEoa = 39, - CallStackDepth = 40, + ContractCreation = 37, + IsPrecompileFromEoa = 38, + CallStackDepth = 39, /// Transaction logs list length - LogsLen = 41, - LogsDataLen = 42, - LogsPayloadLen = 43, - TxnNumberBefore = 44, - TxnNumberAfter = 45, + LogsLen = 40, + LogsDataLen = 41, + LogsPayloadLen = 42, + TxnNumberBefore = 43, + TxnNumberAfter = 44, - KernelHash = 46, - KernelLen = 47, + KernelHash = 45, + KernelLen = 46, } impl GlobalMetadata { - pub(crate) const COUNT: usize = 48; + pub(crate) const COUNT: usize = 47; pub(crate) const fn all() -> [Self; Self::COUNT] { [ @@ -108,7 +104,6 @@ impl GlobalMetadata { Self::StateTrieRootDigestAfter, Self::TransactionTrieRootDigestAfter, Self::ReceiptTrieRootDigestAfter, - Self::TrieEncodedChildSize, Self::BlockBeneficiary, Self::BlockTimestamp, Self::BlockNumber, @@ -162,7 +157,6 @@ impl GlobalMetadata { Self::StateTrieRootDigestAfter => "GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER", Self::TransactionTrieRootDigestAfter => "GLOBAL_METADATA_TXN_TRIE_DIGEST_AFTER", Self::ReceiptTrieRootDigestAfter => "GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_AFTER", - Self::TrieEncodedChildSize => "GLOBAL_METADATA_TRIE_ENCODED_CHILD_SIZE", Self::BlockBeneficiary => "GLOBAL_METADATA_BLOCK_BENEFICIARY", Self::BlockTimestamp => "GLOBAL_METADATA_BLOCK_TIMESTAMP", Self::BlockNumber => "GLOBAL_METADATA_BLOCK_NUMBER", diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index 6e2a0015..fa25fa87 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use ethereum_types::U256; use hex_literal::hex; +use static_assertions::const_assert; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; @@ -86,12 +87,23 @@ pub(crate) fn evm_constants() -> HashMap { c } -const MISC_CONSTANTS: [(&str, [u8; 32]); 1] = [ +const MISC_CONSTANTS: [(&str, [u8; 32]); 3] = [ // Base for limbs used in bignum arithmetic. ( "BIGNUM_LIMB_BASE", hex!("0000000000000000000000000000000100000000000000000000000000000000"), ), + // Position in SEGMENT_RLP_RAW where the empty node encoding is stored. It is + // equal to usize::MAX so that all rlp pointers all much smalled than that + ( + "ENCODED_EMPTY_NODE_POS", + hex!("00000000000000000000000000000000000000000000000000000000FFFFFFFF"), + ), + // 0x10000 = 2^16 bytes, much larger than any RLP blob the EVM could possibly create. + ( + "MAX_RLP_BLOB_SIZE", + hex!("0000000000000000000000000000000000000000000000000000000000010000"), + ), ]; const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [ diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index c4376721..58de9e34 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -140,12 +140,14 @@ enum InterpreterMemOpKind { impl<'a> Interpreter<'a> { pub(crate) fn new_with_kernel(initial_offset: usize, initial_stack: Vec) -> Self { - Self::new( + let mut result = Self::new( &KERNEL.code, initial_offset, initial_stack, &KERNEL.prover_inputs, - ) + ); + result.initialize_rlp_segment(); + result } pub(crate) fn new( @@ -1171,6 +1173,18 @@ impl<'a> Interpreter<'a> { } self.generation_state.registers.context = context; } + + /// Writes the encoding of 0 to position @ + pub(crate) fn initialize_rlp_segment(&mut self) { + self.generation_state.memory.set( + MemoryAddress { + context: 0, + segment: Segment::RlpRaw as usize, + virt: 0xFFFFFFFF, + }, + 128.into(), + ) + } } // Computes the two's complement of the given integer. diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index 20c98bf9..f985ebd4 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -201,21 +201,36 @@ fn test_extcodecopy() -> Result<()> { prepare_interpreter(&mut interpreter, address, &account)?; let context = interpreter.context(); - interpreter.generation_state.memory.contexts[context].segments - [Segment::ContextMetadata as usize] - .set(GasLimit as usize, U256::from(1000000000000u64)); + interpreter.generation_state.memory.set( + MemoryAddress { + context, + segment: Segment::ContextMetadata as usize, + virt: GasLimit as usize, + }, + U256::from(1000000000000u64), + ); let extcodecopy = KERNEL.global_labels["sys_extcodecopy"]; // Put random data in main memory and the `KernelAccountCode` segment for realism. let mut rng = thread_rng(); for i in 0..2000 { - interpreter.generation_state.memory.contexts[context].segments - [Segment::MainMemory as usize] - .set(i, U256::from(rng.gen::())); - interpreter.generation_state.memory.contexts[context].segments - [Segment::KernelAccountCode as usize] - .set(i, U256::from(rng.gen::())); + interpreter.generation_state.memory.set( + MemoryAddress { + context, + segment: Segment::MainMemory as usize, + virt: i, + }, + U256::from(rng.gen::()), + ); + interpreter.generation_state.memory.set( + MemoryAddress { + context, + segment: Segment::KernelAccountCode as usize, + virt: i, + }, + U256::from(rng.gen::()), + ); } // Random inputs @@ -250,9 +265,11 @@ fn test_extcodecopy() -> Result<()> { assert!(interpreter.stack().is_empty()); // Check that the code was correctly copied to memory. for i in 0..size { - let memory = interpreter.generation_state.memory.contexts[context].segments - [Segment::MainMemory as usize] - .get(dest_offset + i); + let memory = interpreter.generation_state.memory.get(MemoryAddress { + context, + segment: Segment::MainMemory as usize, + virt: dest_offset + i, + }); assert_eq!( memory, code.get(offset + i).copied().unwrap_or_default().into() @@ -277,13 +294,22 @@ fn prepare_interpreter_all_accounts( // Switch context and initialize memory with the data we need for the tests. interpreter.generation_state.registers.program_counter = 0; interpreter.set_code(1, code.to_vec()); - interpreter.generation_state.memory.contexts[1].segments[Segment::ContextMetadata as usize] - .set( - ContextMetadata::Address as usize, - U256::from_big_endian(&addr), - ); - interpreter.generation_state.memory.contexts[1].segments[Segment::ContextMetadata as usize] - .set(ContextMetadata::GasLimit as usize, 100_000.into()); + interpreter.generation_state.memory.set( + MemoryAddress { + context: 1, + segment: Segment::ContextMetadata as usize, + virt: ContextMetadata::Address as usize, + }, + U256::from_big_endian(&addr), + ); + interpreter.generation_state.memory.set( + MemoryAddress { + context: 1, + segment: Segment::ContextMetadata as usize, + virt: ContextMetadata::GasLimit as usize, + }, + 100_000.into(), + ); interpreter.set_context(1); interpreter.set_is_kernel(false); interpreter.generation_state.memory.set( diff --git a/evm/src/cpu/kernel/tests/add11.rs b/evm/src/cpu/kernel/tests/add11.rs index 9ba65db2..b85bfe66 100644 --- a/evm/src/cpu/kernel/tests/add11.rs +++ b/evm/src/cpu/kernel/tests/add11.rs @@ -19,6 +19,7 @@ use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::proof::TrieRoots; use crate::util::h2u; +use crate::witness::memory::MemoryAddress; // Stolen from `tests/mpt/insert.rs` // Prepare the interpreter by loading the initial MPTs and @@ -199,8 +200,14 @@ fn test_add11_yml() { let route_txn_label = KERNEL.global_labels["hash_initial_tries"]; // Switch context and initialize memory with the data we need for the tests. interpreter.generation_state.registers.program_counter = route_txn_label; - interpreter.generation_state.memory.contexts[0].segments[Segment::ContextMetadata as usize] - .set(ContextMetadata::GasLimit as usize, 1_000_000.into()); + interpreter.generation_state.memory.set( + MemoryAddress { + context: 0, + segment: Segment::ContextMetadata as usize, + virt: ContextMetadata::GasLimit as usize, + }, + 1_000_000.into(), + ); interpreter.set_is_kernel(true); interpreter.run().expect("Proving add11 failed."); } diff --git a/evm/src/cpu/kernel/tests/mpt/insert.rs b/evm/src/cpu/kernel/tests/mpt/insert.rs index 9c2fd50b..acd42e8f 100644 --- a/evm/src/cpu/kernel/tests/mpt/insert.rs +++ b/evm/src/cpu/kernel/tests/mpt/insert.rs @@ -12,11 +12,12 @@ use crate::cpu::kernel::tests::mpt::{ }; use crate::generation::mpt::AccountRlp; use crate::generation::TrieInputs; +use crate::util::u256_to_usize; use crate::Node; #[test] fn mpt_insert_empty() -> Result<()> { - test_state_trie(Default::default(), nibbles_64(0xABC), test_account_2()) + test_state_trie(Default::default(), nibbles_64(0xDEF), test_account_2()) } #[test] @@ -233,6 +234,7 @@ fn test_state_trie( let hash = H256::from_uint(&interpreter.stack()[1]); state_trie.insert(k, rlp::encode(&account).to_vec()); + let expected_state_trie_hash = state_trie.hash(); assert_eq!(hash, expected_state_trie_hash); diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index a3ba3302..e5dbc3e7 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -35,7 +35,7 @@ pub mod mpt; pub(crate) mod prover_input; pub(crate) mod rlp; pub(crate) mod state; -mod trie_extractor; +pub(crate) mod trie_extractor; use self::mpt::{load_all_mpts, TrieRootPtrs}; use crate::witness::util::mem_write_log; @@ -296,121 +296,14 @@ pub fn generate_traces, const D: usize>( Ok((tables, public_values)) } -fn _simulate_cpu, const D: usize>( - state: &mut GenerationState, -) -> anyhow::Result<()> { - let halt_pc = KERNEL.global_labels["halt"]; - - loop { - // If we've reached the kernel's halt routine, and our trace length is a power of 2, stop. - let pc = state.registers.program_counter; - let halt = state.registers.is_kernel && pc == halt_pc; - if halt { - log::info!("CPU halted after {} cycles", state.traces.clock()); - - // Padding - let mut row = CpuColumnsView::::default(); - row.clock = F::from_canonical_usize(state.traces.clock()); - row.context = F::from_canonical_usize(state.registers.context); - row.program_counter = F::from_canonical_usize(pc); - row.is_kernel_mode = F::ONE; - row.gas = F::from_canonical_u64(state.registers.gas_used); - row.stack_len = F::from_canonical_usize(state.registers.stack_len); - - loop { - state.traces.push_cpu(row); - row.clock += F::ONE; - if state.traces.clock().is_power_of_two() { - break; - } - } - - log::info!("CPU trace padded to {} cycles", state.traces.clock()); - - return Ok(()); - } - - transition(state)?; - } -} - -fn __simulate_cpu, const D: usize>( - state: &mut GenerationState, -) -> anyhow::Result<()> { - let mut profiling_map = HashMap::::new(); - - let halt_pc = KERNEL.global_labels["halt"]; - - loop { - // If we've reached the kernel's halt routine, and our trace length is a power of 2, stop. - let pc = state.registers.program_counter; - if let Ok(idx) = KERNEL - .ordered_labels - .binary_search_by_key(&pc, |label| KERNEL.global_labels[label]) - { - profiling_map - .entry(KERNEL.ordered_labels[idx].clone()) - .and_modify(|counter| *counter += 1) - .or_insert(1); - } - let halt = state.registers.is_kernel && pc == halt_pc; - if halt { - log::info!("CPU halted after {} cycles", state.traces.clock()); - - // Padding - let mut row = CpuColumnsView::::default(); - row.clock = F::from_canonical_usize(state.traces.clock()); - row.context = F::from_canonical_usize(state.registers.context); - row.program_counter = F::from_canonical_usize(pc); - row.is_kernel_mode = F::ONE; - row.gas = F::from_canonical_u64(state.registers.gas_used); - row.stack_len = F::from_canonical_usize(state.registers.stack_len); - - loop { - state.traces.push_cpu(row); - row.clock += F::ONE; - if state.traces.clock().is_power_of_two() { - break; - } - } - log::info!("CPU trace padded to {} cycles", state.traces.clock()); - - let mut sorted_labels: Vec<_> = profiling_map.iter().collect(); - sorted_labels.sort_unstable_by_key(|item| item.1); - sorted_labels.reverse(); - log::info!("Offsets: {:?}", sorted_labels); - - return Ok(()); - } - - transition(state)?; - } -} - fn simulate_cpu, const D: usize>( state: &mut GenerationState, ) -> anyhow::Result<()> { - let mut profiling_map = HashMap::::new(); - let halt_pc = KERNEL.global_labels["halt"]; loop { // If we've reached the kernel's halt routine, and our trace length is a power of 2, stop. let pc = state.registers.program_counter; - let idx = match KERNEL - .ordered_labels - .binary_search_by_key(&pc, |label| KERNEL.global_labels[label]) - { - Ok(idx) => Some(idx), - Err(0) => None, - Err(idx) => Some(idx - 1), - }; - if let Some(idx) = idx { - profiling_map - .entry(KERNEL.ordered_labels[idx].clone()) - .and_modify(|counter| *counter += 1) - .or_insert(1); - } let halt = state.registers.is_kernel && pc == halt_pc; if halt { log::info!("CPU halted after {} cycles", state.traces.clock()); @@ -431,679 +324,12 @@ fn simulate_cpu, const D: usize>( break; } } - log::info!("CPU trace padded to {} cycles", state.traces.clock()); - let mut sorted_labels: Vec<_> = profiling_map.iter().collect(); - sorted_labels.sort_unstable_by_key(|item| item.1); - sorted_labels.reverse(); - log::info!("Offsets: {:?}", sorted_labels); + log::info!("CPU trace padded to {} cycles", state.traces.clock()); return Ok(()); } transition(state)?; - { - let _ = [ - ("secp_add_valid_points_no_edge_case", 10980), - ("ecrecover", 9009), - ("num_bytes", 7306), - ("hex_prefix_rlp", 5820), - ("secp_double", 4076), - ("encode_node_branch", 3408), - ("mstore_unpacking", 2368), - ("main", 2320), - ("secp_add_valid_points", 2281), - ("insert_accessed_addresses", 2238), - ("decode_int_given_len", 1809), - ("read_rlp_to_memory", 1626), - ("load_mpt", 1355), - ("encode_or_hash_node", 1160), - ("mpt_read_branch", 1152), - ("mpt_read", 1065), - ("encode_node", 803), - ("memcpy_bytes", 731), - ("encode_account", 662), - ("prepend_rlp_list_prefix", 602), - ("pack_small_rlp", 590), - ("secp_precompute_table", 477), - ("encode_node_leaf", 459), - ("mstore_unpacking_rlp", 448), - ("maybe_hash_node", 438), - ("encode_node_empty", 413), - ("encode_rlp_fixed", 380), - ("insert_touched_addresses", 368), - ("mpt_read_extension_not_found", 340), - ("mpt_read_state_trie", 323), - ("sys_sstore", 313), - ("debug_it_should_be_128", 295), - ("process_receipt", 292), - ("process_type_0_txn", 283), - ("encode_rlp_scalar", 271), - ("check_bloom_loop", 269), - ("mpt_insert_hash_node", 252), - ("initialize_block_bloom", 247), - ("encode_rlp_list_prefix", 221), - ("encode_rlp_multi_byte_string_prefix", 216), - ("mpt_load_state_trie_value", 213), - ("mload_packing", 204), - ("mpt_hash", 198), - ("decode_rlp_string_len", 197), - ("jumpdest_analysis", 164), - ("load_code", 155), - ("process_normalized_txn", 154), - ("secp_glv_decompose", 148), - ("process_message_txn_code_loaded", 145), - ("insert_accessed_storage_keys", 135), - ("delete_all_touched_addresses", 128), - ("mpt_read_leaf_not_found", 119), - ("encode_receipt", 113), - ("increment_nonce", 108), - ("add_eth", 93), - ("process_message_txn", 82), - ("process_message_txn_after_call", 77), - ("doubly_encode_rlp_scalar", 74), - ("deduct_eth", 72), - ("intrinsic_gas", 64), - ("hash_final_tries", 58), - ("update_txn_trie", 58), - ("terminate_common", 53), - ("extcodehash", 45), - ("warm_precompiles", 45), - ("sys_stop", 42), - ("start_txn", 41), - ("mpt_insert", 39), - ("load_all_mpts", 38), - ("sload_current", 36), - ("encode_txn", 36), - ("scalar_to_rlp", 35), - ("encode_rlp_string", 34), - ("hash_initial_tries", 33), - ("encode_node_branch_prepend_prefix", 32), - ("decode_rlp_scalar", 28), - ("encode_rlp_string_small", 24), - ("route_txn", 24), - ("mpt_hash_storage_trie", 24), - ("encode_rlp_string_large", 23), - ("buy_gas", 20), - ("mpt_insert_receipt_trie", 17), - ("transfer_eth", 17), - ("decode_rlp_list_len", 17), - ("mpt_insert_txn_trie", 16), - ("balance", 15), - ("mpt_hash_txn_trie", 14), - ("mpt_hash_receipt_trie", 14), - ("mpt_hash_state_trie", 14), - ("logs_bloom", 13), - ("delete_all_selfdestructed_addresses", 13), - ("encode_rlp_string_large_after_writing_len", 13), - ("txn_after", 12), - ("encode_rlp_256", 12), - ("encode_storage_value", 12), - ("increment_bounded_rlp", 11), - ("withdrawals", 10), - ("warm_coinbase", 9), - ("nonce", 9), - ("increment_sender_nonce", 9), - ("process_based_on_type", 8), - ("after_storage_read", 7), - ("mpt_read_empty", 7), - ("ec_double_retself", 6), - ("warm_origin", 5), - ("add_bignum", 5), - ("check_bloom_loop_end", 4), - ("execute_withdrawals", 3), - ("encode_rlp_160", 3), - ("charge_gas_hook", 2), - ("halt", 1), - ("jumped_to_0", 1), - ]; - let _ = [ - ("secp_add_valid_points_no_edge_case", 10980), - ("ecrecover", 9009), - ("num_bytes", 7306), - ("hex_prefix_rlp", 5820), - ("secp_double", 4076), - ("encode_node_branch", 3408), - ("mstore_unpacking", 2368), - ("main", 2306), - ("secp_add_valid_points", 2281), - ("insert_accessed_addresses", 2238), - ("decode_int_given_len", 1809), - ("encode_node_empty", 1652), - ("read_rlp_to_memory", 1626), - ("load_mpt", 1355), - ("encode_or_hash_node", 1160), - ("mpt_read_branch", 1152), - ("mpt_read", 1065), - ("encode_node", 803), - ("memcpy_bytes", 731), - ("encode_account", 662), - ("prepend_rlp_list_prefix", 602), - ("pack_small_rlp", 590), - ("secp_precompute_table", 477), - ("encode_node_leaf", 459), - ("mstore_unpacking_rlp", 448), - ("maybe_hash_node", 438), - ("encode_rlp_fixed", 380), - ("insert_touched_addresses", 368), - ("mpt_read_extension_not_found", 340), - ("mpt_read_state_trie", 323), - ("sys_sstore", 313), - ("hash_final_tries", 305), - ("process_receipt", 292), - ("process_type_0_txn", 283), - ("encode_rlp_scalar", 271), - ("check_bloom_loop", 269), - ("mpt_insert_hash_node", 252), - ("encode_rlp_list_prefix", 221), - ("encode_rlp_multi_byte_string_prefix", 216), - ("mpt_load_state_trie_value", 213), - ("mload_packing", 204), - ("mpt_hash", 198), - ("decode_rlp_string_len", 197), - ("jumpdest_analysis", 164), - ("load_code", 155), - ("process_normalized_txn", 154), - ("secp_glv_decompose", 148), - ("process_message_txn_code_loaded", 145), - ("insert_accessed_storage_keys", 135), - ("delete_all_touched_addresses", 128), - ("mpt_read_leaf_not_found", 119), - ("encode_receipt", 113), - ("increment_nonce", 108), - ("add_eth", 93), - ("process_message_txn", 82), - ("process_message_txn_after_call", 77), - ("doubly_encode_rlp_scalar", 74), - ("deduct_eth", 72), - ("intrinsic_gas", 64), - ("update_txn_trie", 58), - ("terminate_common", 53), - ("warm_precompiles", 45), - ("extcodehash", 45), - ("sys_stop", 42), - ("start_txn", 41), - ("mpt_insert", 39), - ("load_all_mpts", 38), - ("sload_current", 36), - ("encode_txn", 36), - ("scalar_to_rlp", 35), - ("encode_rlp_string", 34), - ("hash_initial_tries", 33), - ("encode_node_branch_prepend_prefix", 32), - ("decode_rlp_scalar", 28), - ("route_txn", 24), - ("mpt_hash_storage_trie", 24), - ("encode_rlp_string_small", 24), - ("encode_rlp_string_large", 23), - ("buy_gas", 20), - ("decode_rlp_list_len", 17), - ("transfer_eth", 17), - ("mpt_insert_receipt_trie", 17), - ("mpt_insert_txn_trie", 16), - ("balance", 15), - ("mpt_hash_receipt_trie", 14), - ("mpt_hash_txn_trie", 14), - ("mpt_hash_state_trie", 14), - ("delete_all_selfdestructed_addresses", 13), - ("logs_bloom", 13), - ("encode_rlp_string_large_after_writing_len", 13), - ("encode_storage_value", 12), - ("encode_rlp_256", 12), - ("txn_after", 12), - ("increment_bounded_rlp", 11), - ("withdrawals", 10), - ("nonce", 9), - ("increment_sender_nonce", 9), - ("warm_coinbase", 9), - ("process_based_on_type", 8), - ("after_storage_read", 7), - ("mpt_read_empty", 7), - ("ec_double_retself", 6), - ("add_bignum", 5), - ("warm_origin", 5), - ("check_bloom_loop_end", 4), - ("encode_rlp_160", 3), - ("execute_withdrawals", 3), - ("charge_gas_hook", 2), - ("halt", 1), - ("jumped_to_0", 1), - ]; - - let _ = [ - ("mstore_unpacking", 148), - ("secp_add_valid_points", 139), - ("secp_add_valid_points_no_edge_case", 132), - ("secp_double", 129), - ("mstore_unpacking_rlp", 112), - ("encode_or_hash_node", 76), - ("encode_node", 72), - ("maybe_hash_node", 72), - ("mload_packing", 68), - ("pack_small_rlp", 59), - ("encode_node_empty", 59), - ("mpt_read", 50), - ("num_bytes", 48), - ("load_mpt", 38), - ("mpt_read_branch", 32), - ("memcpy_bytes", 27), - ("encode_rlp_fixed", 20), - ("encode_rlp_scalar", 19), - ("mpt_read_state_trie", 17), - ("prepend_rlp_list_prefix", 14), - ("encode_rlp_256", 12), - ("mpt_hash", 12), - ("insert_accessed_addresses", 12), - ("decode_rlp_string_len", 9), - ("hex_prefix_rlp", 9), - ("encode_node_leaf", 9), - ("decode_int_given_len", 9), - ("encode_rlp_multi_byte_string_prefix", 8), - ("encode_rlp_list_prefix", 8), - ("decode_rlp_scalar", 7), - ("mpt_hash_storage_trie", 6), - ("encode_account", 6), - ("insert_touched_addresses", 5), - ("encode_node_branch_prepend_prefix", 4), - ("encode_node_branch", 4), - ("mpt_load_state_trie_value", 3), - ("extcodehash", 3), - ("mpt_insert", 3), - ("add_eth", 3), - ("mpt_hash_state_trie", 2), - ("encode_rlp_string", 2), - ("deduct_eth", 2), - ("mpt_hash_txn_trie", 2), - ("ec_double_retself", 2), - ("mpt_hash_receipt_trie", 2), - ("secp_glv_decompose", 2), - ("charge_gas_hook", 2), - ("sys_sstore", 1), - ("increment_sender_nonce", 1), - ("buy_gas", 1), - ("main", 1), - ("process_type_0_txn", 1), - ("jumpdest_analysis", 1), - ("txn_after", 1), - ("encode_rlp_160", 1), - ("intrinsic_gas", 1), - ("delete_all_selfdestructed_addresses", 1), - ("encode_rlp_string_large_after_writing_len", 1), - ("jumped_to_0", 1), - ("decode_rlp_list_len", 1), - ("mpt_read_empty", 1), - ("hash_final_tries", 1), - ("sload_current", 1), - ("encode_txn", 1), - ("start_txn", 1), - ("encode_rlp_string_large", 1), - ("load_code", 1), - ("increment_bounded_rlp", 1), - ("encode_receipt", 1), - ("process_message_txn", 1), - ("ecrecover", 1), - ("warm_origin", 1), - ("encode_rlp_string_small", 1), - ("process_based_on_type", 1), - ("secp_precompute_table", 1), - ("halt", 1), - ("update_txn_trie", 1), - ("transfer_eth", 1), - ("logs_bloom", 1), - ("read_rlp_to_memory", 1), - ("encode_storage_value", 1), - ("process_receipt", 1), - ("process_message_txn_code_loaded", 1), - ("increment_nonce", 1), - ("delete_all_touched_addresses", 1), - ("terminate_common", 1), - ("balance", 1), - ("withdrawals", 1), - ("sys_stop", 1), - ("after_storage_read", 1), - ("mpt_insert_receipt_trie", 1), - ("hash_initial_tries", 1), - ("doubly_encode_rlp_scalar", 1), - ("route_txn", 1), - ("mpt_insert_txn_trie", 1), - ("warm_coinbase", 1), - ("load_all_mpts", 1), - ("warm_precompiles", 1), - ("add_bignum", 1), - ("insert_accessed_storage_keys", 1), - ("process_normalized_txn", 1), - ("scalar_to_rlp", 1), - ("nonce", 1), - ("process_message_txn_after_call", 1), - ("execute_withdrawals", 1), - ]; - let _ = [ - ("secp_add_valid_points_no_edge_case", 10980), - ("ecrecover", 9009), - ("num_bytes", 7306), - ("hex_prefix_rlp", 5820), - ("secp_double", 4076), - ("encode_node_branch", 3440), - ("encode_or_hash_node", 2991), - ("mstore_unpacking", 2368), - ("main", 2306), - ("secp_add_valid_points", 2281), - ("insert_accessed_addresses", 2238), - ("decode_int_given_len", 1809), - ("encode_node_empty", 1652), - ("read_rlp_to_memory", 1626), - ("load_mpt", 1355), - ("mpt_read_branch", 1152), - ("mpt_read", 1065), - ("memcpy_bytes", 731), - ("encode_account", 662), - ("prepend_rlp_list_prefix", 602), - ("hash_final_tries", 578), - ("secp_precompute_table", 477), - ("encode_node_leaf", 459), - ("mstore_unpacking_rlp", 448), - ("encode_rlp_fixed", 380), - ("insert_touched_addresses", 368), - ("mpt_read_extension_not_found", 340), - ("mpt_read_state_trie", 323), - ("sys_sstore", 313), - ("process_receipt", 292), - ("process_type_0_txn", 283), - ("encode_rlp_scalar", 271), - ("mpt_insert_hash_node", 252), - ("encode_rlp_list_prefix", 221), - ("encode_rlp_multi_byte_string_prefix", 216), - ("mpt_load_state_trie_value", 213), - ("mload_packing", 204), - ("mpt_hash", 198), - ("decode_rlp_string_len", 197), - ("jumpdest_analysis", 164), - ("load_code", 155), - ("process_normalized_txn", 154), - ("secp_glv_decompose", 148), - ("process_message_txn_code_loaded", 145), - ("insert_accessed_storage_keys", 135), - ("delete_all_touched_addresses", 128), - ("mpt_read_leaf_not_found", 119), - ("encode_receipt", 113), - ("increment_nonce", 108), - ("add_eth", 93), - ("process_message_txn", 82), - ("process_message_txn_after_call", 77), - ("doubly_encode_rlp_scalar", 74), - ("deduct_eth", 72), - ("intrinsic_gas", 64), - ("update_txn_trie", 58), - ("terminate_common", 53), - ("warm_precompiles", 45), - ("extcodehash", 45), - ("sys_stop", 42), - ("start_txn", 41), - ("mpt_insert", 39), - ("load_all_mpts", 38), - ("encode_txn", 36), - ("sload_current", 36), - ("scalar_to_rlp", 35), - ("encode_rlp_string", 34), - ("hash_initial_tries", 33), - ("decode_rlp_scalar", 28), - ("route_txn", 24), - ("mpt_hash_storage_trie", 24), - ("encode_rlp_string_small", 24), - ("encode_rlp_string_large", 23), - ("buy_gas", 20), - ("transfer_eth", 17), - ("mpt_insert_receipt_trie", 17), - ("decode_rlp_list_len", 17), - ("mpt_insert_txn_trie", 16), - ("balance", 15), - ("mpt_hash_txn_trie", 14), - ("mpt_hash_receipt_trie", 14), - ("mpt_hash_state_trie", 14), - ("delete_all_selfdestructed_addresses", 13), - ("logs_bloom", 13), - ("encode_rlp_string_large_after_writing_len", 13), - ("encode_storage_value", 12), - ("encode_rlp_256", 12), - ("txn_after", 12), - ("increment_bounded_rlp", 11), - ("withdrawals", 10), - ("increment_sender_nonce", 9), - ("warm_coinbase", 9), - ("nonce", 9), - ("process_based_on_type", 8), - ("after_storage_read", 7), - ("mpt_read_empty", 7), - ("ec_double_retself", 6), - ("add_bignum", 5), - ("warm_origin", 5), - ("encode_rlp_160", 3), - ("execute_withdrawals", 3), - ("charge_gas_hook", 2), - ("jumped_to_0", 1), - ("halt", 1), - ]; - - let _ = [ - ("secp_add_valid_points_no_edge_case", 10980), - ("ecrecover", 9009), - ("num_bytes", 7306), - ("hex_prefix_rlp", 5820), - ("secp_double", 4076), - ("encode_node_branch", 3440), - ("mstore_unpacking", 2368), - ("main", 2306), - ("secp_add_valid_points", 2281), - ("insert_accessed_addresses", 2238), - ("decode_int_given_len", 1809), - ("encode_node_empty", 1652), - ("read_rlp_to_memory", 1626), - ("load_mpt", 1355), - ("encode_or_hash_node", 1160), - ("mpt_read_branch", 1152), - ("mpt_read", 1065), - ("encode_node", 803), - ("memcpy_bytes", 731), - ("encode_account", 662), - ("prepend_rlp_list_prefix", 602), - ("pack_small_rlp", 590), - ("hash_final_tries", 578), - ("secp_precompute_table", 477), - ("encode_node_leaf", 459), - ("mstore_unpacking_rlp", 448), - ("maybe_hash_node", 438), - ("encode_rlp_fixed", 380), - ("insert_touched_addresses", 368), - ("mpt_read_extension_not_found", 340), - ("mpt_read_state_trie", 323), - ("sys_sstore", 313), - ("process_receipt", 292), - ("process_type_0_txn", 283), - ("encode_rlp_scalar", 271), - ("mpt_insert_hash_node", 252), - ("encode_rlp_list_prefix", 221), - ("encode_rlp_multi_byte_string_prefix", 216), - ("mpt_load_state_trie_value", 213), - ("mload_packing", 204), - ("mpt_hash", 198), - ("decode_rlp_string_len", 197), - ("jumpdest_analysis", 164), - ("load_code", 155), - ("process_normalized_txn", 154), - ("secp_glv_decompose", 148), - ("process_message_txn_code_loaded", 145), - ("insert_accessed_storage_keys", 135), - ("delete_all_touched_addresses", 128), - ("mpt_read_leaf_not_found", 119), - ("encode_receipt", 113), - ("increment_nonce", 108), - ("add_eth", 93), - ("process_message_txn", 82), - ("process_message_txn_after_call", 77), - ("doubly_encode_rlp_scalar", 74), - ("deduct_eth", 72), - ("intrinsic_gas", 64), - ("update_txn_trie", 58), - ("terminate_common", 53), - ("extcodehash", 45), - ("warm_precompiles", 45), - ("sys_stop", 42), - ("start_txn", 41), - ("mpt_insert", 39), - ("load_all_mpts", 38), - ("encode_txn", 36), - ("sload_current", 36), - ("scalar_to_rlp", 35), - ("encode_rlp_string", 34), - ("hash_initial_tries", 33), - ("decode_rlp_scalar", 28), - ("route_txn", 24), - ("mpt_hash_storage_trie", 24), - ("encode_rlp_string_small", 24), - ("encode_rlp_string_large", 23), - ("buy_gas", 20), - ("decode_rlp_list_len", 17), - ("transfer_eth", 17), - ("mpt_insert_receipt_trie", 17), - ("mpt_insert_txn_trie", 16), - ("balance", 15), - ("mpt_hash_txn_trie", 14), - ("mpt_hash_receipt_trie", 14), - ("mpt_hash_state_trie", 14), - ("encode_rlp_string_large_after_writing_len", 13), - ("logs_bloom", 13), - ("delete_all_selfdestructed_addresses", 13), - ("txn_after", 12), - ("encode_storage_value", 12), - ("encode_rlp_256", 12), - ("increment_bounded_rlp", 11), - ("withdrawals", 10), - ("nonce", 9), - ("increment_sender_nonce", 9), - ("warm_coinbase", 9), - ("process_based_on_type", 8), - ("mpt_read_empty", 7), - ("after_storage_read", 7), - ("ec_double_retself", 6), - ("add_bignum", 5), - ("warm_origin", 5), - ("encode_rlp_160", 3), - ("execute_withdrawals", 3), - ("charge_gas_hook", 2), - ("halt", 1), - ("jumped_to_0", 1), - ]; - - let _ = [ - ("secp_add_valid_points_no_edge_case", 10980), - ("ecrecover", 9009), - ("num_bytes", 7306), - ("hex_prefix_rlp", 5820), - ("secp_double", 4076), - ("encode_node_branch", 3408), - ("mstore_unpacking", 2368), - ("main", 2306), - ("secp_add_valid_points", 2281), - ("insert_accessed_addresses", 2238), - ("decode_int_given_len", 1809), - ("encode_node_empty", 1652), - ("read_rlp_to_memory", 1626), - ("load_mpt", 1355), - ("encode_or_hash_node", 1160), - ("mpt_read_branch", 1152), - ("mpt_read", 1065), - ("encode_node", 803), - ("memcpy_bytes", 731), - ("encode_account", 662), - ("prepend_rlp_list_prefix", 602), - ("pack_small_rlp", 590), - ("hash_final_tries", 578), - ("secp_precompute_table", 477), - ("encode_node_leaf", 459), - ("mstore_unpacking_rlp", 448), - ("maybe_hash_node", 438), - ("encode_rlp_fixed", 380), - ("insert_touched_addresses", 368), - ("mpt_read_extension_not_found", 340), - ("mpt_read_state_trie", 323), - ("sys_sstore", 313), - ("process_receipt", 292), - ("process_type_0_txn", 283), - ("encode_rlp_scalar", 271), - ("mpt_insert_hash_node", 252), - ("encode_rlp_list_prefix", 221), - ("encode_rlp_multi_byte_string_prefix", 216), - ("mpt_load_state_trie_value", 213), - ("mload_packing", 204), - ("mpt_hash", 198), - ("decode_rlp_string_len", 197), - ("jumpdest_analysis", 164), - ("load_code", 155), - ("process_normalized_txn", 154), - ("secp_glv_decompose", 148), - ("process_message_txn_code_loaded", 145), - ("insert_accessed_storage_keys", 135), - ("delete_all_touched_addresses", 128), - ("mpt_read_leaf_not_found", 119), - ("encode_receipt", 113), - ("increment_nonce", 108), - ("add_eth", 93), - ("process_message_txn", 82), - ("process_message_txn_after_call", 77), - ("doubly_encode_rlp_scalar", 74), - ("deduct_eth", 72), - ("intrinsic_gas", 64), - ("update_txn_trie", 58), - ("terminate_common", 53), - ("extcodehash", 45), - ("warm_precompiles", 45), - ("sys_stop", 42), - ("start_txn", 41), - ("mpt_insert", 39), - ("load_all_mpts", 38), - ("encode_txn", 36), - ("sload_current", 36), - ("scalar_to_rlp", 35), - ("encode_rlp_string", 34), - ("hash_initial_tries", 33), - ("encode_node_branch_prepend_prefix", 32), - ("decode_rlp_scalar", 28), - ("mpt_hash_storage_trie", 24), - ("route_txn", 24), - ("encode_rlp_string_small", 24), - ("encode_rlp_string_large", 23), - ("buy_gas", 20), - ("transfer_eth", 17), - ("mpt_insert_receipt_trie", 17), - ("decode_rlp_list_len", 17), - ("mpt_insert_txn_trie", 16), - ("balance", 15), - ("mpt_hash_txn_trie", 14), - ("mpt_hash_state_trie", 14), - ("mpt_hash_receipt_trie", 14), - ("delete_all_selfdestructed_addresses", 13), - ("logs_bloom", 13), - ("encode_rlp_string_large_after_writing_len", 13), - ("txn_after", 12), - ("encode_rlp_256", 12), - ("encode_storage_value", 12), - ("increment_bounded_rlp", 11), - ("withdrawals", 10), - ("warm_coinbase", 9), - ("increment_sender_nonce", 9), - ("nonce", 9), - ("process_based_on_type", 8), - ("mpt_read_empty", 7), - ("after_storage_read", 7), - ("ec_double_retself", 6), - ("add_bignum", 5), - ("warm_origin", 5), - ("encode_rlp_160", 3), - ("execute_withdrawals", 3), - ("charge_gas_hook", 2), - ("halt", 1), - ("jumped_to_0", 1), - ]; - } } } diff --git a/evm/src/memory/segments.rs b/evm/src/memory/segments.rs index 6e67e619..48a17222 100644 --- a/evm/src/memory/segments.rs +++ b/evm/src/memory/segments.rs @@ -1,3 +1,5 @@ +use ethereum_types::U256; + #[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)] pub(crate) enum Segment { /// Contains EVM bytecode. @@ -29,46 +31,42 @@ pub(crate) enum Segment { RlpRaw = 12, /// Contains all trie data. It is owned by the kernel, so it only lives on context 0. TrieData = 13, - /// A buffer used to store the encodings of a branch node's children. - TrieEncodedChild = 14, - /// A buffer used to store the lengths of the encodings of a branch node's children. - TrieEncodedChildLen = 15, /// A table of values 2^i for i=0..255 for use with shift /// instructions; initialised by `kernel/asm/shift.asm::init_shift_table()`. - ShiftTable = 16, - JumpdestBits = 17, - EcdsaTable = 18, - BnWnafA = 19, - BnWnafB = 20, - BnTableQ = 21, - BnPairing = 22, + ShiftTable = 14, + JumpdestBits = 15, + EcdsaTable = 16, + BnWnafA = 17, + BnWnafB = 18, + BnTableQ = 19, + BnPairing = 20, /// List of addresses that have been accessed in the current transaction. - AccessedAddresses = 23, + AccessedAddresses = 21, /// List of storage keys that have been accessed in the current transaction. - AccessedStorageKeys = 24, + AccessedStorageKeys = 22, /// List of addresses that have called SELFDESTRUCT in the current transaction. - SelfDestructList = 25, + SelfDestructList = 23, /// Contains the bloom filter of a transaction. - TxnBloom = 26, + TxnBloom = 24, /// Contains the bloom filter present in the block header. - GlobalBlockBloom = 27, + GlobalBlockBloom = 25, /// List of log pointers pointing to the LogsData segment. - Logs = 28, - LogsData = 29, + Logs = 26, + LogsData = 27, /// Journal of state changes. List of pointers to `JournalData`. Length in `GlobalMetadata`. - Journal = 30, - JournalData = 31, - JournalCheckpoints = 32, + Journal = 28, + JournalData = 29, + JournalCheckpoints = 30, /// List of addresses that have been touched in the current transaction. - TouchedAddresses = 33, + TouchedAddresses = 31, /// List of checkpoints for the current context. Length in `ContextMetadata`. - ContextCheckpoints = 34, + ContextCheckpoints = 32, /// List of 256 previous block hashes. - BlockHashes = 35, + BlockHashes = 33, } impl Segment { - pub(crate) const COUNT: usize = 36; + pub(crate) const COUNT: usize = 34; pub(crate) const fn all() -> [Self; Self::COUNT] { [ @@ -86,8 +84,6 @@ impl Segment { Self::TxnData, Self::RlpRaw, Self::TrieData, - Self::TrieEncodedChild, - Self::TrieEncodedChildLen, Self::ShiftTable, Self::JumpdestBits, Self::EcdsaTable, @@ -128,8 +124,6 @@ impl Segment { Segment::TxnData => "SEGMENT_TXN_DATA", Segment::RlpRaw => "SEGMENT_RLP_RAW", Segment::TrieData => "SEGMENT_TRIE_DATA", - Segment::TrieEncodedChild => "SEGMENT_TRIE_ENCODED_CHILD", - Segment::TrieEncodedChildLen => "SEGMENT_TRIE_ENCODED_CHILD_LEN", Segment::ShiftTable => "SEGMENT_SHIFT_TABLE", Segment::JumpdestBits => "SEGMENT_JUMPDEST_BITS", Segment::EcdsaTable => "SEGMENT_KERNEL_ECDSA_TABLE", @@ -169,8 +163,6 @@ impl Segment { Segment::TxnData => 8, Segment::RlpRaw => 8, Segment::TrieData => 256, - Segment::TrieEncodedChild => 256, - Segment::TrieEncodedChildLen => 6, Segment::ShiftTable => 256, Segment::JumpdestBits => 1, Segment::EcdsaTable => 256, @@ -193,4 +185,17 @@ impl Segment { Segment::BlockHashes => 256, } } + + pub(crate) fn constant(&self, virt: usize) -> Option { + match self { + Segment::RlpRaw => { + if virt == 0xFFFFFFFF { + Some(U256::from(0x80)) + } else { + None + } + } + _ => None, + } + } } diff --git a/evm/src/witness/memory.rs b/evm/src/witness/memory.rs index 8cb7daf7..f39073c0 100644 --- a/evm/src/witness/memory.rs +++ b/evm/src/witness/memory.rs @@ -177,6 +177,11 @@ impl MemoryState { } let segment = Segment::all()[address.segment]; + + if let Some(constant) = Segment::constant(&segment, address.virt) { + return constant; + } + let val = self.contexts[address.context].segments[address.segment].get(address.virt); assert!( val.bits() <= segment.bit_range(), @@ -194,6 +199,15 @@ impl MemoryState { } let segment = Segment::all()[address.segment]; + + if let Some(constant) = Segment::constant(&segment, address.virt) { + assert!( + constant == val, + "Attempting to set constant {} to incorrect value", + address.virt + ); + return; + } assert!( val.bits() <= segment.bit_range(), "Value {} exceeds {:?} range of {} bits",