mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 14:23:07 +00:00
158 lines
6.4 KiB
NASM
158 lines
6.4 KiB
NASM
// Given an address, return a pointer to the associated (length-prefixed)
|
|
// account data, which consists of four words (nonce, balance, storage_root,
|
|
// code_hash), in the state trie. Returns 0 if the address is not found.
|
|
global mpt_read_state_trie:
|
|
// stack: addr, retdest
|
|
// The key is the hash of the address. Since KECCAK_GENERAL takes input from
|
|
// memory, we will write addr bytes to SEGMENT_KERNEL_GENERAL[0..20] first.
|
|
%stack (addr) -> (0, @SEGMENT_KERNEL_GENERAL, 0, addr, 20, mpt_read_state_trie_after_mstore)
|
|
%jump(mstore_unpacking)
|
|
mpt_read_state_trie_after_mstore:
|
|
// stack: retdest
|
|
%stack () -> (0, @SEGMENT_KERNEL_GENERAL, 0, 20) // context, segment, offset, len
|
|
KECCAK_GENERAL
|
|
// stack: key, retdest
|
|
PUSH 64 // num_nibbles
|
|
%mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) // node_ptr
|
|
// stack: node_ptr, num_nibbles, key, retdest
|
|
%jump(mpt_read)
|
|
|
|
// Read a value from a MPT.
|
|
//
|
|
// Arguments:
|
|
// - the virtual address of the trie to search in
|
|
// - the key, as a U256
|
|
// - the number of nibbles in the key (should start at 64)
|
|
//
|
|
// This function returns a pointer to the length-prefixed leaf, or 0 if the key is not found.
|
|
global mpt_read:
|
|
// stack: node_ptr, num_nibbles, key, retdest
|
|
DUP1
|
|
%mload_trie_data
|
|
// stack: node_type, node_ptr, num_nibbles, key, retdest
|
|
// Increment node_ptr, so it points to the node payload instead of its type.
|
|
SWAP1 %increment SWAP1
|
|
// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
|
|
|
|
DUP1 %eq_const(@MPT_NODE_EMPTY) %jumpi(mpt_read_empty)
|
|
DUP1 %eq_const(@MPT_NODE_BRANCH) %jumpi(mpt_read_branch)
|
|
DUP1 %eq_const(@MPT_NODE_EXTENSION) %jumpi(mpt_read_extension)
|
|
DUP1 %eq_const(@MPT_NODE_LEAF) %jumpi(mpt_read_leaf)
|
|
|
|
// There's still the MPT_NODE_HASH case, but if we hit a hash node,
|
|
// it means the prover failed to provide necessary Merkle data, so panic.
|
|
PANIC
|
|
|
|
mpt_read_empty:
|
|
// Return 0 to indicate that the value was not found.
|
|
%stack (node_type, node_payload_ptr, num_nibbles, key, retdest)
|
|
-> (retdest, 0)
|
|
JUMP
|
|
|
|
mpt_read_branch:
|
|
// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
|
|
POP
|
|
// stack: node_payload_ptr, num_nibbles, key, retdest
|
|
DUP2 // num_nibbles
|
|
ISZERO
|
|
// stack: num_nibbles == 0, node_payload_ptr, num_nibbles, key, retdest
|
|
%jumpi(mpt_read_branch_end_of_key)
|
|
|
|
// We have not reached the end of the key, so we descend to one of our children.
|
|
// stack: node_payload_ptr, num_nibbles, key, retdest
|
|
%stack (node_payload_ptr, num_nibbles, key)
|
|
-> (num_nibbles, key, node_payload_ptr)
|
|
// stack: num_nibbles, key, node_payload_ptr, retdest
|
|
%split_first_nibble
|
|
%stack (first_nibble, num_nibbles, key, node_payload_ptr)
|
|
-> (node_payload_ptr, first_nibble, num_nibbles, key)
|
|
// child_ptr = load(node_payload_ptr + first_nibble)
|
|
ADD %mload_trie_data
|
|
// stack: child_ptr, num_nibbles, key, retdest
|
|
%jump(mpt_read) // recurse
|
|
|
|
mpt_read_branch_end_of_key:
|
|
%stack (node_payload_ptr, num_nibbles, key, retdest) -> (node_payload_ptr, retdest)
|
|
// stack: node_payload_ptr, retdest
|
|
%add_const(16) // skip over the 16 child nodes
|
|
// stack: value_ptr_ptr, retdest
|
|
%mload_trie_data
|
|
// stack: value_len_ptr, retdest
|
|
DUP1 %mload_trie_data
|
|
// stack: value_len, value_len_ptr, retdest
|
|
%jumpi(mpt_read_branch_found_value)
|
|
// This branch node contains no value, so return null.
|
|
%stack (value_len_ptr, retdest) -> (retdest, 0)
|
|
mpt_read_branch_found_value:
|
|
// stack: value_len_ptr, retdest
|
|
%increment
|
|
// stack: value_ptr, retdest
|
|
SWAP1
|
|
JUMP
|
|
|
|
mpt_read_extension:
|
|
// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
|
|
%stack (node_type, node_payload_ptr, num_nibbles, key)
|
|
-> (num_nibbles, key, node_payload_ptr)
|
|
// stack: num_nibbles, key, node_payload_ptr, retdest
|
|
DUP3 %mload_trie_data
|
|
// stack: node_num_nibbles, num_nibbles, key, node_payload_ptr, retdest
|
|
SWAP1
|
|
SUB
|
|
// stack: future_nibbles, key, node_payload_ptr, retdest
|
|
DUP2 DUP2
|
|
// stack: future_nibbles, key, future_nibbles, key, node_payload_ptr, retdest
|
|
%mul_const(4) SHR // key_part = key >> (future_nibbles * 4)
|
|
DUP1
|
|
// stack: key_part, key_part, future_nibbles, key, node_payload_ptr, retdest
|
|
DUP5 %increment %mload_trie_data
|
|
// stack: node_key, key_part, key_part, future_nibbles, key, node_payload_ptr, retdest
|
|
EQ // does the first part of our key match the node's key?
|
|
%jumpi(mpt_read_extension_found)
|
|
// Not found; return 0.
|
|
%stack (key_part, future_nibbles, node_payload_ptr, retdest) -> (retdest, 0)
|
|
JUMP
|
|
mpt_read_extension_found:
|
|
// stack: key_part, future_nibbles, key, node_payload_ptr, retdest
|
|
DUP2 %mul_const(4) SHL // key_part_shifted = (key_part << (future_nibbles * 4))
|
|
// stack: key_part_shifted, future_nibbles, key, node_payload_ptr, retdest
|
|
%stack (key_part_shifted, future_nibbles, key)
|
|
-> (key, key_part_shifted, future_nibbles)
|
|
SUB // key -= key_part_shifted
|
|
// stack: key, future_nibbles, node_payload_ptr, retdest
|
|
SWAP2
|
|
// stack: node_payload_ptr, future_nibbles, key, retdest
|
|
%add_const(2) // child pointer is third field of extension node
|
|
%mload_trie_data
|
|
// stack: child_ptr, future_nibbles, key, retdest
|
|
%jump(mpt_read) // recurse
|
|
|
|
mpt_read_leaf:
|
|
// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
|
|
POP
|
|
// stack: node_payload_ptr, num_nibbles, key, retdest
|
|
DUP1 %mload_trie_data
|
|
// stack: node_num_nibbles, node_payload_ptr, num_nibbles, key, retdest
|
|
DUP2 %increment %mload_trie_data
|
|
// stack: node_key, node_num_nibbles, node_payload_ptr, num_nibbles, key, retdest
|
|
SWAP3
|
|
// stack: num_nibbles, node_num_nibbles, node_payload_ptr, node_key, key, retdest
|
|
EQ
|
|
%stack (num_nibbles_match, node_payload_ptr, node_key, key)
|
|
-> (key, node_key, num_nibbles_match, node_payload_ptr)
|
|
EQ
|
|
AND
|
|
// stack: keys_match && num_nibbles_match, node_payload_ptr, retdest
|
|
%jumpi(mpt_read_leaf_found)
|
|
// Not found; return 0.
|
|
%stack (node_payload_ptr, retdest) -> (retdest, 0)
|
|
JUMP
|
|
mpt_read_leaf_found:
|
|
// stack: node_payload_ptr, retdest
|
|
%add_const(2) // The value pointer is located after num_nibbles and the key.
|
|
// stack: value_ptr_ptr, retdest
|
|
%mload_trie_data
|
|
// stack: value_ptr, retdest
|
|
SWAP1
|
|
JUMP
|