2022-10-08 22:27:57 -07:00

207 lines
6.4 KiB
NASM

// TODO: Receipt trie leaves are variable-length, so we need to be careful not
// to permit buffer over-reads.
// Load all partial trie data from prover inputs.
global load_all_mpts:
// stack: retdest
// First set @GLOBAL_METADATA_TRIE_DATA_SIZE = 1.
// We don't want it to start at 0, as we use 0 as a null pointer.
PUSH 1
%set_trie_data_size
%load_mpt %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT)
%load_mpt %mstore_global_metadata(@GLOBAL_METADATA_TXN_TRIE_ROOT)
%load_mpt %mstore_global_metadata(@GLOBAL_METADATA_RECEIPT_TRIE_ROOT)
PROVER_INPUT(mpt)
// stack: num_storage_tries, retdest
DUP1 %mstore_global_metadata(@GLOBAL_METADATA_NUM_STORAGE_TRIES)
// stack: num_storage_tries, retdest
PUSH 0 // i = 0
// stack: i, num_storage_tries, retdest
storage_trie_loop:
DUP2 DUP2 EQ
// stack: i == num_storage_tries, i, num_storage_tries, retdest
%jumpi(storage_trie_loop_end)
// stack: i, num_storage_tries, retdest
PROVER_INPUT(mpt)
// stack: storage_trie_addr, i, num_storage_tries, retdest
DUP2
// stack: i, storage_trie_addr, i, num_storage_tries, retdest
%mstore_kernel(@SEGMENT_STORAGE_TRIE_ADDRS)
// stack: i, num_storage_tries, retdest
%load_mpt
// stack: root_ptr, i, num_storage_tries, retdest
DUP2
// stack: i, root_ptr, i, num_storage_tries, retdest
%mstore_kernel(@SEGMENT_STORAGE_TRIE_PTRS)
// stack: i, num_storage_tries, retdest
%jump(storage_trie_loop)
storage_trie_loop_end:
// stack: i, num_storage_tries, retdest
%pop2
// stack: retdest
JUMP
// Load an MPT from prover inputs.
// Pre stack: retdest
// Post stack: node_ptr
load_mpt:
// stack: retdest
PROVER_INPUT(mpt)
// stack: node_type, retdest
DUP1 %eq_const(@MPT_NODE_EMPTY) %jumpi(load_mpt_empty)
DUP1 %eq_const(@MPT_NODE_BRANCH) %jumpi(load_mpt_branch)
DUP1 %eq_const(@MPT_NODE_EXTENSION) %jumpi(load_mpt_extension)
DUP1 %eq_const(@MPT_NODE_LEAF) %jumpi(load_mpt_leaf)
DUP1 %eq_const(@MPT_NODE_HASH) %jumpi(load_mpt_digest)
PANIC // Invalid node type
load_mpt_empty:
// TRIE_DATA[0] = 0, and an empty node has type 0, so we can simply return the null pointer.
%stack (node_type, retdest) -> (retdest, 0)
JUMP
load_mpt_branch:
// stack: node_type, retdest
%get_trie_data_size
// stack: node_ptr, node_type, retdest
SWAP1 %append_to_trie_data
// stack: node_ptr, retdest
// Save the offset of our 16 child pointers so we can write them later.
// Then advance out current trie pointer beyond them, so we can load the
// value and have it placed after our child pointers.
%get_trie_data_size
// stack: children_ptr, node_ptr, retdest
DUP1 %add_const(17) // Skip over 16 children plus the value pointer
// stack: value_ptr, children_ptr, node_ptr, retdest
%set_trie_data_size
// stack: children_ptr, node_ptr, retdest
%load_value
// stack: children_ptr, value_ptr, node_ptr, retdest
SWAP1
// Load the 16 children.
%rep 16
%load_mpt
// stack: child_ptr, next_child_ptr_ptr, value_ptr, node_ptr, retdest
DUP2
// stack: next_child_ptr_ptr, child_ptr, next_child_ptr_ptr, value_ptr, node_ptr, retdest
%mstore_trie_data
// stack: next_child_ptr_ptr, value_ptr, node_ptr, retdest
%increment
// stack: next_child_ptr_ptr, value_ptr, node_ptr, retdest
%endrep
// stack: value_ptr_ptr, value_ptr, node_ptr, retdest
%mstore_trie_data
// stack: node_ptr, retdest
SWAP1
JUMP
load_mpt_extension:
// stack: node_type, retdest
%get_trie_data_size
// stack: node_ptr, node_type, retdest
SWAP1 %append_to_trie_data
// stack: node_ptr, retdest
PROVER_INPUT(mpt) // read num_nibbles
%append_to_trie_data
PROVER_INPUT(mpt) // read packed_nibbles
%append_to_trie_data
// stack: node_ptr, retdest
%get_trie_data_size
// stack: child_ptr_ptr, node_ptr, retdest
// Increment trie_data_size, to leave room for child_ptr_ptr, before we load our child.
DUP1 %increment %set_trie_data_size
// stack: child_ptr_ptr, node_ptr, retdest
%load_mpt
// stack: child_ptr, child_ptr_ptr, node_ptr, retdest
SWAP1
%mstore_trie_data
// stack: node_ptr, retdest
SWAP1
JUMP
load_mpt_leaf:
// stack: node_type, retdest
%get_trie_data_size
// stack: node_ptr, node_type, retdest
SWAP1 %append_to_trie_data
// stack: node_ptr, retdest
PROVER_INPUT(mpt) // read num_nibbles
%append_to_trie_data
PROVER_INPUT(mpt) // read packed_nibbles
%append_to_trie_data
// stack: node_ptr, retdest
// We save value_ptr_ptr = get_trie_data_size, then increment trie_data_size
// to skip over the slot for value_ptr. We will write value_ptr after the
// load_value call.
%get_trie_data_size
// stack: value_ptr_ptr, node_ptr, retdest
DUP1 %increment %set_trie_data_size
// stack: value_ptr_ptr, node_ptr, retdest
%load_value
// stack: value_ptr, value_ptr_ptr, node_ptr, retdest
SWAP1 %mstore_trie_data
// stack: node_ptr, retdest
SWAP1
JUMP
load_mpt_digest:
// stack: node_type, retdest
%get_trie_data_size
// stack: node_ptr, node_type, retdest
SWAP1 %append_to_trie_data
// stack: node_ptr, retdest
PROVER_INPUT(mpt) // read digest
%append_to_trie_data
// stack: node_ptr, retdest
SWAP1
JUMP
// Convenience macro to call load_mpt and return where we left off.
%macro load_mpt
PUSH %%after
%jump(load_mpt)
%%after:
%endmacro
// Load a leaf from prover input, append it to trie data, and return a pointer to it.
%macro load_value
// stack: (empty)
PROVER_INPUT(mpt)
// stack: value_len
DUP1 ISZERO
%jumpi(%%return_null)
// stack: value_len
%get_trie_data_size
SWAP1
// stack: value_len, value_ptr
DUP1 %append_to_trie_data
// stack: value_len, value_ptr
%%loop:
DUP1 ISZERO
// stack: value_len == 0, value_len, value_ptr
%jumpi(%%finish_loop)
// stack: value_len, value_ptr
PROVER_INPUT(mpt)
// stack: leaf_part, value_len, value_ptr
%append_to_trie_data
// stack: value_len, value_ptr
%decrement
// stack: value_len', value_ptr
%jump(%%loop)
%%finish_loop:
// stack: value_len, value_ptr
POP
// stack: value_ptr
%jump(%%end)
%%return_null:
%stack (value_len) -> (0)
%%end:
%endmacro