diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_addresses.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_addresses.asm index 8c2de08bd..cf7b97b28 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_addresses.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_addresses.asm @@ -5,7 +5,8 @@ // Post stack: address global get_create_address: // stack: sender, nonce, retdest - %alloc_rlp_block + PUSH @INITIAL_RLP_ADDR + %add_const(@MAX_RLP_PREFIX_SIZE) // stack: rlp_start, sender, nonce, retdest %stack (rlp_start, sender, nonce) -> (rlp_start, sender, nonce, rlp_start) // stack: rlp_start, sender, nonce, rlp_start, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm index bd378abde..edcd3f329 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm @@ -10,7 +10,7 @@ // - write the receipt in MPT_TRIE_DATA , // - insert a new node in receipt_trie, // - set the bloom filter back to 0 -global process_receipt: +global process_receipt: // stack: status, leftover_gas, prev_cum_gas, txn_nb, num_nibbles, retdest DUP2 DUP4 // stack: prev_cum_gas, leftover_gas, status, leftover_gas, prev_cum_gas, txn_nb, num_nibbles, retdest @@ -54,10 +54,9 @@ process_receipt_after_bloom: // Now we can write the receipt in MPT_TRIE_DATA. %get_trie_data_size // stack: receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest - // Write transaction type if necessary. The address INITIAL_TXN_RLP_ADDR contains the current transaction type. - PUSH @INITIAL_TXN_RLP_ADDR - MLOAD_GENERAL - // stack: first_txn_byte, receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest + // Write transaction type if necessary. + %mload_txn_field(@TXN_FIELD_TYPE) + // stack: txn_type, receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest DUP1 %eq_const(1) %jumpi(receipt_nonzero_type) DUP1 %eq_const(2) %jumpi(receipt_nonzero_type) DUP1 %eq_const(3) %jumpi(receipt_nonzero_type) diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index f2663347a..c21c39ae6 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -69,8 +69,7 @@ global main: // Initialize the RLP DATA pointer to its initial position, // skipping over the preinitialized empty node. - PUSH @INITIAL_TXN_RLP_ADDR - %add_const(@MAX_RLP_BLOB_SIZE) + PUSH @INITIAL_RLP_ADDR %mstore_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) // Encode constant nodes @@ -110,9 +109,11 @@ global hash_initial_tries: PUSH 8 MUL %increment // stack: init_trie_data_len - + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, init_trie_data_len %mpt_hash_txn_trie %mload_global_metadata(@GLOBAL_METADATA_TXN_TRIE_DIGEST_BEFORE) %assert_eq - // stack: trie_data_len + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, trie_data_len %mpt_hash_receipt_trie %mload_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_BEFORE) %assert_eq // stack: trie_data_full_len // Check that the trie data length is correct. @@ -181,10 +182,14 @@ global perform_final_checks: // since the final transaction and receipt tries have already been // added to `GLOBAL_METADATA_TRIE_DATA_SIZE`. PUSH 1 + PUSH @INITIAL_RLP_ADDR global check_txn_trie: + // stack: rlp_start, dummy_trie_len %mpt_hash_txn_trie %mload_global_metadata(@GLOBAL_METADATA_TXN_TRIE_DIGEST_AFTER) %assert_eq + PUSH @INITIAL_RLP_ADDR global check_receipt_trie: + // stack: rlp_start, dummy_trie_len %mpt_hash_receipt_trie %mload_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_DIGEST_AFTER) %assert_eq global check_state_trie: // First, check initial trie. @@ -203,6 +208,9 @@ global check_state_trie: %mstore_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) %set_initial_tries + + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, trie_data_len %mpt_hash_state_trie // stack: init_state_hash, trie_data_len @@ -218,6 +226,8 @@ global check_state_trie: PUSH 1 global check_final_state_trie: %set_final_tries + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, dummy_trie_len %mpt_hash_state_trie %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) %assert_eq // We don't need the trie data length here. POP diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash.asm index e2c460d1a..42c77b754 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash.asm @@ -1,4 +1,5 @@ -// Computes the Merkle root of the given trie node. +// Computes the Merkle root of the given trie node. RLP encoding (if any) will +// start at position `rlp_start`. // // encode_value is a function which should take as input // - the position within @SEGMENT_RLP_RAW to write to, @@ -12,11 +13,11 @@ // Given the initial length of the `TrieData` segment, it also updates the length // for the current trie. // -// Pre stack: node_ptr, encode_value, cur_len, retdest +// Pre stack: node_ptr, rlp_start, encode_value, cur_len, retdest // Post stack: hash, new_len global mpt_hash: - // stack: node_ptr, encode_value, cur_len, retdest - %stack (node_ptr, encode_value, cur_len) -> (node_ptr, encode_value, cur_len, mpt_hash_hash_if_rlp) + // stack: node_ptr, rlp_start, encode_value, cur_len, retdest + %stack (node_ptr, rlp_start, encode_value, cur_len) -> (node_ptr, rlp_start, encode_value, cur_len, mpt_hash_hash_if_rlp) %jump(encode_or_hash_node) mpt_hash_hash_if_rlp: // stack: result, result_len, new_len, retdest @@ -47,13 +48,13 @@ 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, cur_len, retdest +// Pre stack: node_ptr, rlp_start, encode_value, cur_len, retdest // Post stack: result, result_len, cur_len global encode_or_hash_node: DUP1 %mload_trie_data // Check if we're dealing with a concrete node, i.e. not a hash node. - // stack: node_type, node_ptr, encode_value, cur_len, retdest + // stack: node_type, node_ptr, rlp_start, encode_value, cur_len, retdest DUP1 PUSH @MPT_NODE_HASH SUB @@ -61,21 +62,21 @@ global encode_or_hash_node: // If we got here, node_type == @MPT_NODE_HASH. // Load the hash and return (hash, 32). - // stack: node_type, node_ptr, encode_value, cur_len, retdest + // stack: node_type, node_ptr, rlp_start, encode_value, cur_len, retdest POP - // stack: node_ptr, encode_value, cur_len, retdest + // stack: node_ptr, rlp_start, encode_value, cur_len, retdest %increment // Skip over node type prefix - // stack: hash_ptr, encode_value, cur_len, retdest + // stack: hash_ptr, rlp_start, encode_value, cur_len, retdest %mload_trie_data - // stack: hash, encode_value, cur_len, retdest + // stack: hash, rlp_start, encode_value, cur_len, retdest // Update the length of the `TrieData` segment: there are only two // elements in a hash node. - SWAP2 %add_const(2) - %stack (cur_len, encode_value, hash, retdest) -> (retdest, hash, 32, cur_len) + SWAP3 %add_const(2) + %stack (cur_len, rlp_start, encode_value, hash, retdest) -> (retdest, hash, 32, cur_len) JUMP encode_or_hash_concrete_node: - %stack (node_type, node_ptr, encode_value, cur_len) -> (node_type, node_ptr, encode_value, cur_len, maybe_hash_node) + %stack (node_type, node_ptr, rlp_start, encode_value, cur_len) -> (node_type, node_ptr, rlp_start, encode_value, cur_len, maybe_hash_node) %jump(encode_node) maybe_hash_node: // stack: result_addr, result_len, cur_len, retdest @@ -99,13 +100,13 @@ 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, cur_len, retdest +// Pre stack: node_type, node_ptr, rlp_start, encode_value, cur_len, retdest // Post stack: result_ptr, result_len, cur_len encode_node: - // stack: node_type, node_ptr, encode_value, cur_len, retdest + // stack: node_type, node_ptr, rlp_start, 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 + // stack: node_type, node_payload_ptr, rlp_start, encode_value, cur_len, retdest DUP1 %eq_const(@MPT_NODE_EMPTY) %jumpi(encode_node_empty) DUP1 %eq_const(@MPT_NODE_BRANCH) %jumpi(encode_node_branch) @@ -117,21 +118,24 @@ encode_node: PANIC global encode_node_empty: - // stack: node_type, node_payload_ptr, encode_value, cur_len, retdest - %pop3 + // stack: node_type, node_payload_ptr, rlp_start, encode_value, cur_len, retdest + %pop4 %stack (cur_len, retdest) -> (retdest, @ENCODED_EMPTY_NODE_ADDR, 1, cur_len) JUMP global encode_node_branch: - // stack: node_type, node_payload_ptr, encode_value, cur_len, retdest + // stack: node_type, node_payload_ptr, rlp_start, encode_value, cur_len, retdest POP // `TrieData` stores the node type, 16 children pointers, and a value pointer. - SWAP2 %add_const(18) SWAP2 - // stack: node_payload_ptr, encode_value, cur_len, retdest + SWAP3 %add_const(18) SWAP3 + // stack: node_payload_ptr, rlp_start, encode_value, cur_len, retdest + SWAP1 - // Allocate a block of RLP memory - %alloc_rlp_block DUP1 + // stack: rlp_start, node_payload_ptr, encode_value, cur_len, retdest + // We leave room to prepend the prefix later. + %add_const(@MAX_RLP_PREFIX_SIZE) + DUP1 // stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len retdest // Call encode_or_hash_node on each child @@ -179,10 +183,10 @@ encode_node_branch_prepend_prefix: %macro encode_child(i) // stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest PUSH %%after_encode - 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 + DUP6 DUP6 DUP4 DUP7 + // stack: node_payload_ptr, rlp_pos, 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, cur_len, %%after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest + // stack: child_i_ptr, rlp_pos, encode_value, cur_len, %%after_encode, rlp_pos, rlp_start, node_payload_ptr, encode_value, cur_len, retdest %jump(encode_or_hash_node) %%after_encode: // stack: result, result_len, cur_len, rlp_pos, rlp_start, node_payload_ptr, encode_value, old_len, retdest @@ -206,17 +210,18 @@ encode_node_branch_prepend_prefix: %endmacro global encode_node_extension: - // stack: node_type, node_payload_ptr, encode_value, cur_len, retdest - SWAP3 %add_const(4) SWAP3 - %stack (node_type, node_payload_ptr, encode_value, cur_len) - -> (node_payload_ptr, encode_value, cur_len, encode_node_extension_after_encode_child, node_payload_ptr) + // stack: node_type, node_payload_ptr, rlp_start, encode_value, cur_len, retdest + SWAP4 %add_const(4) SWAP4 + %stack (node_type, node_payload_ptr, rlp_start, encode_value, cur_len) + -> (node_payload_ptr, rlp_start, encode_value, cur_len, encode_node_extension_after_encode_child, rlp_start, node_payload_ptr) %add_const(2) %mload_trie_data - // stack: child_ptr, encode_value, cur_len, encode_node_extension_after_encode_child, node_payload_ptr, retdest + // stack: child_ptr, rlp_start, encode_value, cur_len, encode_node_extension_after_encode_child, rlp_start, node_payload_ptr, retdest %jump(encode_or_hash_node) encode_node_extension_after_encode_child: - // stack: result, result_len, cur_len, node_payload_ptr, retdest - %stack (result, result_len, cur_len, node_payload_ptr) -> (result, result_len, node_payload_ptr, cur_len) - %alloc_rlp_block + // stack: result, result_len, cur_len, rlp_start, node_payload_ptr, retdest + %stack (result, result_len, cur_len, rlp_start, node_payload_ptr) -> (rlp_start, result, result_len, node_payload_ptr, cur_len) + // We leave room to prepend the prefix later. + %add_const(@MAX_RLP_PREFIX_SIZE) // stack: rlp_start, result, result_len, node_payload_ptr, cur_len, retdest PUSH encode_node_extension_after_hex_prefix // retdest PUSH 0 // terminated @@ -250,10 +255,13 @@ encode_node_extension_after_unpacking: JUMP global encode_node_leaf: - // stack: node_type, node_payload_ptr, encode_value, cur_len, retdest + // stack: node_type, node_payload_ptr, rlp_start, encode_value, cur_len, retdest POP - // stack: node_payload_ptr, encode_value, cur_len, retdest - %alloc_rlp_block + // stack: node_payload_ptr, rlp_start, encode_value, cur_len, retdest + SWAP1 + // stack: rlp_start, node_payload_ptr, encode_value, cur_len, retdest + // We leave room to prepend the prefix later. + %add_const(@MAX_RLP_PREFIX_SIZE) PUSH encode_node_leaf_after_hex_prefix // retdest PUSH 1 // terminated // stack: terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, cur_len, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm index 1da7c6a31..31fa192fa 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm @@ -1,57 +1,64 @@ // Hashing logic specific to a particular trie. global mpt_hash_state_trie: - // stack: cur_len, retdest + // stack: rlp_start, cur_len, retdest PUSH encode_account + // stack: encode_account, rlp_start, cur_len, retdest + SWAP1 + // stack: rlp_start, encode_account, cur_len, retdest %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) - // stack: node_ptr, encode_account, cur_len, retdest + // stack: node_ptr, rlp_start, encode_account, cur_len, retdest %jump(mpt_hash) %macro mpt_hash_state_trie - // stack: cur_len - PUSH %%after - SWAP1 + // stack: rlp_start, cur_len + %stack (rlp_start, cur_len) -> (rlp_start, cur_len, %%after) %jump(mpt_hash_state_trie) %%after: %endmacro global mpt_hash_storage_trie: - // stack: node_ptr, cur_len, retdest - %stack (node_ptr, cur_len) -> (node_ptr, encode_storage_value, cur_len) + // stack: rlp_start, node_ptr, cur_len, retdest + %stack (rlp_start, node_ptr, cur_len) -> (node_ptr, rlp_start, encode_storage_value, cur_len) %jump(mpt_hash) %macro mpt_hash_storage_trie - %stack (node_ptr, cur_len) -> (node_ptr, cur_len, %%after) + // stack: rlp_start, node_ptr, cur_len + %stack (rlp_start, node_ptr, cur_len) -> (rlp_start, node_ptr, cur_len, %%after) %jump(mpt_hash_storage_trie) %%after: %endmacro global mpt_hash_txn_trie: - // stack: cur_len, retdest + // stack: rlp_start, cur_len, retdest PUSH encode_txn + // stack: encode_txn, rlp_start, cur_len, retdest + SWAP1 + // stack: rlp_start, encode_txn, cur_len, retdest %mload_global_metadata(@GLOBAL_METADATA_TXN_TRIE_ROOT) - // stack: node_ptr, encode_txn, cur_len, retdest + // stack: node_ptr, rlp_start, encode_txn, cur_len, retdest %jump(mpt_hash) %macro mpt_hash_txn_trie - // stack: cur_len - PUSH %%after - SWAP1 + // stack: rlp_start, cur_len + %stack (rlp_start, cur_len) -> (rlp_start, cur_len, %%after) %jump(mpt_hash_txn_trie) %%after: %endmacro global mpt_hash_receipt_trie: - // stack: cur_len, retdest + // stack: rlp_start, cur_len, retdest PUSH encode_receipt + // stack: encode_receipt, rlp_start, cur_len, retdest + SWAP1 + // stack: rlp_start, encode_receipt, cur_len, retdest %mload_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_ROOT) - // stack: node_ptr, encode_receipt, cur_len, retdest + // stack: node_ptr, rlp_start, encode_receipt, cur_len, retdest %jump(mpt_hash) %macro mpt_hash_receipt_trie - // stack: cur_len - PUSH %%after - SWAP1 + // stack: rlp_start, cur_len + %stack (rlp_start, cur_len) -> (rlp_start, cur_len, %%after) %jump(mpt_hash_receipt_trie) %%after: %endmacro @@ -100,6 +107,8 @@ global encode_account: DUP3 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 + DUP3 + // stack: rlp_pos_5, storage_root_ptr, cur_len, rlp_pos_5, value_ptr, cur_len, retdest // Hash storage trie. %mpt_hash_storage_trie diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm index e1e82b562..e4e6061e4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm @@ -62,14 +62,12 @@ mpt_insert_receipt_trie_save: // Post stack: rlp_scalar global scalar_to_rlp: // stack: scalar, retdest - %mload_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) + PUSH @INITIAL_RLP_ADDR // stack: init_addr, scalar, retdest SWAP1 DUP2 %encode_rlp_scalar // stack: addr', init_addr, retdest // Now our rlp_encoding is in RlpRaw. - // Set new RlpRaw data size - DUP1 %mstore_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) DUP2 DUP2 SUB // len of the key // stack: len, addr', init_addr, retdest DUP3 diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/util.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/util.asm index 092710bc8..afa6c7570 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/util.asm @@ -16,23 +16,6 @@ MSTORE_GENERAL %endmacro -%macro alloc_rlp_block - // stack: (empty) - %mload_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) - // stack: block_start - // 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(@MAX_RLP_BLOB_SIZE) - // stack: block_end, block_start - %mstore_global_metadata(@GLOBAL_METADATA_RLP_DATA_SIZE) - // stack: block_start - // We leave an extra 9 bytes, so that callers can later prepend a prefix before block_start. - // (9 is the length of the longest possible RLP list prefix.) - %add_const(9) - // stack: block_start -%endmacro - %macro get_trie_data_size // stack: (empty) %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) diff --git a/evm_arithmetization/src/cpu/kernel/asm/rlp/read_to_memory.asm b/evm_arithmetization/src/cpu/kernel/asm/rlp/read_to_memory.asm index 7c44d61d9..dc6f8fa31 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/rlp/read_to_memory.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/rlp/read_to_memory.asm @@ -8,10 +8,10 @@ global read_rlp_to_memory: // stack: retdest PROVER_INPUT(rlp) // Read the RLP blob length from the prover tape. // stack: len, retdest - PUSH @INITIAL_TXN_RLP_ADDR - %build_kernel_address + PUSH @INITIAL_RLP_ADDR + ADD - PUSH @INITIAL_TXN_RLP_ADDR + PUSH @INITIAL_RLP_ADDR // stack: addr, final_addr, retdest read_rlp_to_memory_loop: // stack: addr, final_addr, retdest @@ -30,9 +30,9 @@ read_rlp_to_memory_loop: read_rlp_to_memory_finish: // stack: addr, final_addr, retdest - // we recover the offset here - PUSH @INITIAL_TXN_RLP_ADDR + // we recover the length here + PUSH @INITIAL_RLP_ADDR DUP3 SUB - // stack: pos, addr, final_addr, retdest - %stack(pos, addr, final_addr, retdest) -> (retdest, pos) + // stack: len, addr, final_addr, retdest + %stack(len, addr, final_addr, retdest) -> (retdest, len) JUMP \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/router.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/router.asm index f2b5c47aa..e7c7f88ee 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/router.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/router.asm @@ -18,27 +18,27 @@ read_txn_from_memory: // Type 0 (legacy) transactions have no such prefix, but their RLP will have a // first byte >= 0xc0, so there is no overlap. - PUSH @INITIAL_TXN_RLP_ADDR + PUSH @INITIAL_RLP_ADDR DUP1 MLOAD_GENERAL %eq_const(1) - // stack: first_byte == 1, rlp_segment, retdest + // stack: first_byte == 1, rlp_start_addr, retdest %jumpi(process_type_1_txn) - // stack: rlp_segment, retdest + // stack: rlp_start_addr, retdest DUP1 MLOAD_GENERAL %eq_const(2) - // stack: first_byte == 2, rlp_segment, retdest + // stack: first_byte == 2, rlp_start_addr, retdest %jumpi(process_type_2_txn) - // stack: rlp_segment, retdest + // stack: rlp_start_addr, retdest DUP1 MLOAD_GENERAL %eq_const(3) - // stack: first_byte == 3, rlp_segment, retdest + // stack: first_byte == 3, rlp_start_addr, retdest %jumpi(process_type_3_txn) - // stack: rlp_segment, retdest + // stack: rlp_start_addr, retdest // At this point, since it's not a type 1, 2 or 3 transaction, // it must be a legacy (aka type 0) transaction. @@ -59,7 +59,7 @@ global update_txn_trie: // and now copy txn_rlp to the new block %stack (rlp_start, txn_rlp_len, value_ptr, txn_counter, num_nibbles) -> ( @SEGMENT_TRIE_DATA, rlp_start, // dest addr, ctx == 0 - @INITIAL_TXN_RLP_ADDR, // src addr + @INITIAL_RLP_ADDR, // src addr txn_rlp_len, // mcpy len txn_rlp_len, rlp_start, txn_counter, num_nibbles, value_ptr) %build_kernel_address diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm index 5907cc24b..ff7610f6d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm @@ -12,6 +12,11 @@ // keccak256(rlp([nonce, gas_price, gas_limit, to, value, data])) global process_type_0_txn: + // stack: rlp_addr, retdest + // Store txn type. + PUSH 0 + %mstore_txn_field(@TXN_FIELD_TYPE) + // stack: rlp_addr, retdest %decode_rlp_list_len // We don't actually need the length. diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_1.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_1.asm index e98b3fa40..4000221f4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_1.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_1.asm @@ -7,6 +7,11 @@ // data, access_list])) global process_type_1_txn: + // stack: rlp_addr, retdest + // Store txn type. + PUSH 1 + %mstore_txn_field(@TXN_FIELD_TYPE) + // stack: rlp_addr, retdest // Initial rlp address offset of 1 (skipping over the 0x01 byte) %add_const(1) diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_2.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_2.asm index 5fbea33c1..ba35b1402 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_2.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_2.asm @@ -8,6 +8,11 @@ // access_list])) global process_type_2_txn: + // stack: rlp_addr, retdest + // Store txn type. + PUSH 2 + %mstore_txn_field(@TXN_FIELD_TYPE) + // stack: rlp_addr, retdest // Initial rlp address offset of 1 (skipping over the 0x02 byte) %add_const(1) diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_3.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_3.asm index 5b4ed8683..0534c0388 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_3.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_3.asm @@ -7,6 +7,11 @@ // to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes])) global process_type_3_txn: + // stack: rlp_addr, retdest + // Store txn type. + PUSH 3 + %mstore_txn_field(@TXN_FIELD_TYPE) + // stack: rlp_addr, retdest // Initial rlp address offset of 1 (skipping over the 0x03 byte) %add_const(1) diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 8ad829a50..d2b521e3e 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -126,16 +126,16 @@ const MISC_CONSTANTS: [(&str, [u8; 32]); 6] = [ "ENCODED_EMPTY_NODE_ADDR", hex!("0000000000000000000000000000000000000000000000000000000b00000000"), ), - // 0x10000 = 2^16 bytes, much larger than any RLP blob the EVM could possibly create. + // 9 bytes, largest possible RLP prefix in our MPTs. ( - "MAX_RLP_BLOB_SIZE", - hex!("0000000000000000000000000000000000000000000000000000000000010000"), + "MAX_RLP_PREFIX_SIZE", + hex!("0000000000000000000000000000000000000000000000000000000000001001"), ), - // Address where the txn RLP encoding starts. + // Address where RLP encoding generally starts. // It is the offset 1 within SEGMENT_RLP_RAW. // *Note*: Changing this will break some tests. ( - "INITIAL_TXN_RLP_ADDR", + "INITIAL_RLP_ADDR", hex!("0000000000000000000000000000000000000000000000000000000b00000001"), ), // Address where the final registers start. It is the offset 6 within the diff --git a/evm_arithmetization/src/cpu/kernel/constants/txn_fields.rs b/evm_arithmetization/src/cpu/kernel/constants/txn_fields.rs index 9d38a8cf1..24a0b8786 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/txn_fields.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/txn_fields.rs @@ -9,9 +9,10 @@ use crate::memory::segments::Segment; #[repr(usize)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)] pub(crate) enum NormalizedTxnField { + Type = Segment::TxnFields as usize, /// Whether a chain ID was present in the txn data. Type 0 transaction with /// v=27 or v=28 have no chain ID. This affects what fields get signed. - ChainIdPresent = Segment::TxnFields as usize, + ChainIdPresent, ChainId, Nonce, MaxPriorityFeePerGas, @@ -37,7 +38,7 @@ pub(crate) enum NormalizedTxnField { } impl NormalizedTxnField { - pub(crate) const COUNT: usize = 17; + pub(crate) const COUNT: usize = 18; /// Unscales this virtual offset by their respective `Segment` value. #[cfg(test)] @@ -47,6 +48,7 @@ impl NormalizedTxnField { pub(crate) const fn all() -> [Self; Self::COUNT] { [ + Self::Type, Self::ChainIdPresent, Self::ChainId, Self::Nonce, @@ -70,6 +72,7 @@ impl NormalizedTxnField { /// The variable name that gets passed into kernel assembly code. pub(crate) const fn var_name(&self) -> &'static str { match self { + NormalizedTxnField::Type => "TXN_FIELD_TYPE", NormalizedTxnField::ChainIdPresent => "TXN_FIELD_CHAIN_ID_PRESENT", NormalizedTxnField::ChainId => "TXN_FIELD_CHAIN_ID", NormalizedTxnField::Nonce => "TXN_FIELD_NONCE", diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index e66ecd46f..771fa04f6 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -642,6 +642,9 @@ fn sload() -> Result<()> { interpreter .push(interpreter.get_global_metadata_field(GlobalMetadata::TrieDataSize)) // Initial length of the trie data segment, unused. .expect("The stack should not overflow."); + interpreter + .push(0.into()) // rlp_start + .expect("The stack should not overflow."); interpreter.run()?; assert_eq!( diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs index aab61d44e..43d11d085 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs @@ -225,6 +225,9 @@ fn test_state_trie( interpreter .push(interpreter.get_global_metadata_field(GlobalMetadata::TrieDataSize)) // Initial trie data segment size, unused. .expect("The stack should not overflow"); + interpreter + .push(0.into()) // rlp_start + .expect("The stack should not overflow."); interpreter.run()?; assert_eq!( diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs index 59c5fb384..0fc8dd3fd 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs @@ -8,6 +8,7 @@ use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1_rlp, test_account_2_rlp}; use crate::generation::TrieInputs; +use crate::memory::segments::Segment; use crate::Node; // TODO: Test with short leaf. Might need to be a storage trie. @@ -110,6 +111,7 @@ fn mpt_hash_branch_to_leaf() -> Result<()> { fn test_state_trie(trie_inputs: TrieInputs) -> Result<()> { let mpt_hash_state_trie = KERNEL.global_labels["mpt_hash_state_trie"]; + let initial_rlp_addr = Segment::RlpRaw as usize + 1; let initial_stack = vec![]; let mut interpreter: Interpreter = Interpreter::new(0, initial_stack, None); @@ -125,6 +127,9 @@ fn test_state_trie(trie_inputs: TrieInputs) -> Result<()> { interpreter .push(1.into()) // Initial length of the trie data segment, unused. .expect("The stack should not overflow"); + interpreter + .push(initial_rlp_addr.into()) // rlp_start + .expect("The stack should not overflow."); interpreter.run()?; assert_eq!( diff --git a/evm_arithmetization/src/cpu/kernel/tests/receipt.rs b/evm_arithmetization/src/cpu/kernel/tests/receipt.rs index 4c688d3ef..502c76fff 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/receipt.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/receipt.rs @@ -523,6 +523,7 @@ fn test_mpt_insert_receipt() -> Result<()> { // Finally, check that the hashes correspond. let mpt_hash_receipt = KERNEL.global_labels["mpt_hash_receipt_trie"]; + let initial_rlp_addr = Segment::RlpRaw as usize + 1; interpreter.generation_state.registers.program_counter = mpt_hash_receipt; interpreter .push(retdest) @@ -531,6 +532,9 @@ fn test_mpt_insert_receipt() -> Result<()> { .push(1.into()) // Initial length of the trie data segment, unused.; // Initial length of the trie data // segment, unused. .expect("The stack should not overflow"); + interpreter + .push(initial_rlp_addr.into()) // rlp_start + .expect("The stack should not overflow."); interpreter.run()?; assert_eq!( interpreter.stack()[1], diff --git a/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/mod.rs index edbb16291..127270c89 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/mod.rs @@ -15,17 +15,15 @@ pub(crate) fn prepare_interpreter_for_txn_parsing( txn: Vec, ) -> Result<()> { let retaddr = 0xDEADBEEFu32.into(); - const INITIAL_TXN_RLP_ADDR: usize = Segment::RlpRaw as usize + 1; + const INITIAL_RLP_ADDR: usize = Segment::RlpRaw as usize + 1; interpreter.generation_state.registers.program_counter = entry_point; interpreter.push(retaddr).or(Err(anyhow!( "Error in `prepare_interpreter_for_txn_parsing`." )))?; - interpreter - .push(INITIAL_TXN_RLP_ADDR.into()) - .or(Err(anyhow!( - "Error in `prepare_interpreter_for_txn_parsing`." - )))?; + interpreter.push(INITIAL_RLP_ADDR.into()).or(Err(anyhow!( + "Error in `prepare_interpreter_for_txn_parsing`." + )))?; // When we reach process_normalized_txn, we're done with parsing and // normalizing. Processing normalized transactions is outside the scope of