Skip to content

Commit

Permalink
Reuse the same RLP blob
Browse files Browse the repository at this point in the history
  • Loading branch information
hratoanina committed Aug 27, 2024
1 parent e3c41e2 commit fbfcdb8
Show file tree
Hide file tree
Showing 20 changed files with 157 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 14 additions & 4 deletions evm_arithmetization/src/cpu/kernel/asm/main.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down
82 changes: 45 additions & 37 deletions evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash.asm
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -47,35 +48,35 @@ 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
%jumpi(encode_or_hash_concrete_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
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 0 additions & 17 deletions evm_arithmetization/src/cpu/kernel/asm/mpt/util.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit fbfcdb8

Please sign in to comment.