mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 06:13:07 +00:00
Fix clobbering of RLP data memory
This commit is contained in:
parent
2ac4fcdf84
commit
a05ed9fc3a
@ -118,16 +118,19 @@ global encode_node_empty:
|
||||
// stack: node_type, node_payload_ptr, encode_value, retdest
|
||||
%pop3
|
||||
// stack: retdest
|
||||
// An empty node is encoded as a single byte, 0x80, which is the RLP
|
||||
// encoding of the empty string. Write this byte to RLP[0] and return
|
||||
// (0, 1).
|
||||
// An empty node is encoded as a single byte, 0x80, which is the RLP encoding of the empty string.
|
||||
// TODO: Write this byte just once to RLP memory, then we can always return (0, 1).
|
||||
%alloc_rlp_block
|
||||
// stack: rlp_pos, retdest
|
||||
PUSH 0x80
|
||||
PUSH 0
|
||||
// stack: 0x80, rlp_pos, retdest
|
||||
DUP2
|
||||
// stack: rlp_pos, 0x80, rlp_pos, retdest
|
||||
%mstore_rlp
|
||||
%stack (retdest) -> (retdest, 0, 1)
|
||||
%stack (rlp_pos, retdest) -> (retdest, rlp_pos, 1)
|
||||
JUMP
|
||||
|
||||
encode_node_branch:
|
||||
global encode_node_branch:
|
||||
// stack: node_type, node_payload_ptr, encode_value, retdest
|
||||
POP
|
||||
// stack: node_payload_ptr, encode_value, retdest
|
||||
@ -135,6 +138,7 @@ encode_node_branch:
|
||||
// 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)
|
||||
@ -150,41 +154,41 @@ encode_node_branch:
|
||||
// stack: base_offset, node_payload_ptr, encode_value, retdest
|
||||
|
||||
// Now, append each child to our RLP tape.
|
||||
PUSH 9 // rlp_pos; we start at 9 to leave room to prepend a list prefix
|
||||
%alloc_rlp_block DUP1
|
||||
// stack: rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, 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', base_offset, node_payload_ptr, encode_value, retdest
|
||||
// stack: rlp_pos', rlp_start, base_offset, node_payload_ptr, encode_value, retdest
|
||||
|
||||
// We no longer need base_offset.
|
||||
SWAP1
|
||||
POP
|
||||
|
||||
// stack: rlp_pos', node_payload_ptr, encode_value, retdest
|
||||
SWAP1
|
||||
%stack (rlp_pos, rlp_start, base_offset, node_payload_ptr)
|
||||
-> (node_payload_ptr, rlp_pos, rlp_start)
|
||||
%add_const(16)
|
||||
// stack: value_ptr_ptr, rlp_pos', encode_value, retdest
|
||||
// stack: value_ptr_ptr, rlp_pos', rlp_start, encode_value, retdest
|
||||
%mload_trie_data
|
||||
// stack: value_ptr, rlp_pos', encode_value, retdest
|
||||
// stack: value_ptr, rlp_pos', rlp_start, encode_value, retdest
|
||||
DUP1 %jumpi(encode_node_branch_with_value)
|
||||
|
||||
// No value; append the empty string (0x80).
|
||||
// stack: value_ptr, rlp_pos', encode_value, retdest
|
||||
%stack (value_ptr, rlp_pos, encode_value) -> (rlp_pos, 0x80, rlp_pos)
|
||||
// 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', retdest
|
||||
// stack: rlp_pos', rlp_start, retdest
|
||||
%increment
|
||||
// stack: rlp_pos'', retdest
|
||||
// stack: rlp_pos'', rlp_start, retdest
|
||||
%jump(encode_node_branch_prepend_prefix)
|
||||
encode_node_branch_with_value:
|
||||
// stack: value_ptr, rlp_pos', encode_value, retdest
|
||||
%stack (value_ptr, rlp_pos, encode_value)
|
||||
-> (encode_value, rlp_pos, value_ptr, encode_node_branch_prepend_prefix)
|
||||
// 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:
|
||||
// stack: rlp_pos'', retdest
|
||||
// stack: rlp_pos'', rlp_start, retdest
|
||||
%prepend_rlp_list_prefix
|
||||
%stack (start_pos, rlp_len, retdest) -> (retdest, start_pos, rlp_len)
|
||||
// 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.
|
||||
@ -208,27 +212,28 @@ encode_node_branch_prepend_prefix:
|
||||
|
||||
// Part of the encode_node_branch function. Appends the i'th child's RLP.
|
||||
%macro append_child(i)
|
||||
// stack: rlp_pos, base_offset, node_payload_ptr, encode_value, retdest
|
||||
DUP2 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD) // load result
|
||||
DUP3 %add_const($i) %mload_kernel(@SEGMENT_TRIE_ENCODED_CHILD_LEN) // load result_len
|
||||
// stack: result_len, result, rlp_pos, base_offset, node_payload_ptr, encode_value, retdest
|
||||
// stack: rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, 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, retdest
|
||||
// If result_len != 32, result is raw RLP, with an appropriate RLP prefix already.
|
||||
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, base_offset, node_payload_ptr, encode_value, retdest
|
||||
// stack: result_len, result, rlp_pos, rlp_start, base_offset, 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, base_offset, node_payload_ptr, encode_value, retdest)
|
||||
-> (rlp_pos, result, result_len, %%after_unpacking, base_offset, node_payload_ptr, encode_value, retdest)
|
||||
%stack (result_len, result, rlp_pos, rlp_start, base_offset, node_payload_ptr, encode_value, retdest)
|
||||
-> (rlp_pos, result, result_len, %%after_unpacking,
|
||||
rlp_start, base_offset, node_payload_ptr, encode_value, retdest)
|
||||
%jump(mstore_unpacking_rlp)
|
||||
%%after_unpacking:
|
||||
// stack: rlp_pos', base_offset, node_payload_ptr, encode_value, retdest
|
||||
// stack: rlp_pos', rlp_start, base_offset, node_payload_ptr, encode_value, retdest
|
||||
%endmacro
|
||||
|
||||
encode_node_extension:
|
||||
global encode_node_extension:
|
||||
// stack: node_type, node_payload_ptr, encode_value, retdest
|
||||
%stack (node_type, node_payload_ptr, encode_value)
|
||||
-> (node_payload_ptr, encode_value, encode_node_extension_after_encode_child, node_payload_ptr)
|
||||
@ -237,61 +242,66 @@ encode_node_extension:
|
||||
%jump(encode_or_hash_node)
|
||||
encode_node_extension_after_encode_child:
|
||||
// stack: result, result_len, node_payload_ptr, retdest
|
||||
%alloc_rlp_block
|
||||
// stack: rlp_start, result, result_len, node_payload_ptr, retdest
|
||||
PUSH encode_node_extension_after_hex_prefix // retdest
|
||||
PUSH 0 // terminated
|
||||
// stack: terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest
|
||||
DUP5 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1.
|
||||
// stack: packed_nibbles, terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest
|
||||
DUP6 %mload_trie_data // Load the num_nibbles field, which is at index 0.
|
||||
// stack: num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest
|
||||
PUSH 9 // We start at 9 to leave room to prepend the largest possible RLP list header.
|
||||
// stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, result, result_len, node_payload_ptr, retdest
|
||||
// stack: terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest
|
||||
DUP6 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1.
|
||||
// stack: packed_nibbles, terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest
|
||||
DUP7 %mload_trie_data // Load the num_nibbles field, which is at index 0.
|
||||
// stack: num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest
|
||||
DUP5
|
||||
// stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_extension_after_hex_prefix, rlp_start, result, result_len, node_payload_ptr, retdest
|
||||
%jump(hex_prefix_rlp)
|
||||
encode_node_extension_after_hex_prefix:
|
||||
// stack: rlp_pos, result, result_len, node_payload_ptr, retdest
|
||||
// stack: rlp_pos, rlp_start, result, result_len, node_payload_ptr, retdest
|
||||
// If result_len != 32, result is raw RLP, with an appropriate RLP prefix already.
|
||||
DUP3 %sub_const(32) %jumpi(encode_node_extension_unpack)
|
||||
DUP4 %sub_const(32) %jumpi(encode_node_extension_unpack)
|
||||
// Otherwise, result is a hash, and we need to add the prefix 0x80 + 32 = 160.
|
||||
PUSH 160
|
||||
DUP2 // rlp_pos
|
||||
%mstore_rlp
|
||||
%increment // rlp_pos += 1
|
||||
encode_node_extension_unpack:
|
||||
%stack (rlp_pos, result, result_len, node_payload_ptr)
|
||||
-> (rlp_pos, result, result_len, encode_node_extension_after_unpacking)
|
||||
%stack (rlp_pos, rlp_start, result, result_len, node_payload_ptr)
|
||||
-> (rlp_pos, result, result_len, encode_node_extension_after_unpacking, rlp_start)
|
||||
%jump(mstore_unpacking_rlp)
|
||||
encode_node_extension_after_unpacking:
|
||||
// stack: rlp_end_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
%prepend_rlp_list_prefix
|
||||
%stack (rlp_start_pos, rlp_len, retdest) -> (retdest, rlp_start_pos, rlp_len)
|
||||
%stack (rlp_prefix_start_pos, rlp_len, retdest)
|
||||
-> (retdest, rlp_prefix_start_pos, rlp_len)
|
||||
JUMP
|
||||
|
||||
encode_node_leaf:
|
||||
global encode_node_leaf:
|
||||
// stack: node_type, node_payload_ptr, encode_value, retdest
|
||||
POP
|
||||
// stack: node_payload_ptr, encode_value, retdest
|
||||
%alloc_rlp_block
|
||||
PUSH encode_node_leaf_after_hex_prefix // retdest
|
||||
PUSH 1 // terminated
|
||||
// stack: terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest
|
||||
DUP3 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1.
|
||||
// stack: packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest
|
||||
DUP4 %mload_trie_data // Load the num_nibbles field, which is at index 0.
|
||||
// stack: num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest
|
||||
PUSH 9 // We start at 9 to leave room to prepend the largest possible RLP list header.
|
||||
// stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, node_payload_ptr, encode_value, retdest
|
||||
// stack: terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest
|
||||
DUP4 %increment %mload_trie_data // Load the packed_nibbles field, which is at index 1.
|
||||
// stack: packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest
|
||||
DUP5 %mload_trie_data // Load the num_nibbles field, which is at index 0.
|
||||
// stack: num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest
|
||||
DUP5
|
||||
// stack: rlp_start, num_nibbles, packed_nibbles, terminated, encode_node_leaf_after_hex_prefix, rlp_start, node_payload_ptr, encode_value, retdest
|
||||
%jump(hex_prefix_rlp)
|
||||
encode_node_leaf_after_hex_prefix:
|
||||
// stack: rlp_pos, node_payload_ptr, encode_value, retdest
|
||||
SWAP1
|
||||
// stack: rlp_pos, rlp_start, node_payload_ptr, encode_value, retdest
|
||||
SWAP2
|
||||
%add_const(2) // The value pointer starts at index 3, after num_nibbles and packed_nibbles.
|
||||
// stack: value_ptr_ptr, rlp_pos, encode_value, retdest
|
||||
// stack: value_ptr_ptr, rlp_start, rlp_pos, encode_value, retdest
|
||||
%mload_trie_data
|
||||
// stack: value_ptr, rlp_pos, encode_value, retdest
|
||||
%stack (value_ptr, rlp_pos, encode_value, retdest)
|
||||
-> (encode_value, rlp_pos, value_ptr, encode_node_leaf_after_encode_value, retdest)
|
||||
// stack: value_ptr, rlp_start, rlp_pos, encode_value, retdest
|
||||
%stack (value_ptr, rlp_start, rlp_pos, encode_value, retdest)
|
||||
-> (encode_value, rlp_pos, value_ptr, encode_node_leaf_after_encode_value, rlp_start, retdest)
|
||||
JUMP
|
||||
encode_node_leaf_after_encode_value:
|
||||
// stack: rlp_end_pos, retdest
|
||||
// stack: rlp_end_pos, rlp_start, retdest
|
||||
%prepend_rlp_list_prefix
|
||||
%stack (rlp_start_pos, rlp_len, retdest) -> (retdest, rlp_start_pos, rlp_len)
|
||||
%stack (rlp_prefix_start_pos, rlp_len, retdest)
|
||||
-> (retdest, rlp_prefix_start_pos, rlp_len)
|
||||
JUMP
|
||||
|
||||
@ -13,6 +13,17 @@ global mpt_hash_state_trie:
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
global mpt_hash_storage_trie:
|
||||
// stack: node_ptr, retdest
|
||||
%stack (node_ptr) -> (node_ptr, encode_storage_value)
|
||||
%jump(mpt_hash)
|
||||
|
||||
%macro mpt_hash_storage_trie
|
||||
PUSH %%after
|
||||
%jump(mpt_hash_storage_trie)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
global mpt_hash_txn_trie:
|
||||
// stack: retdest
|
||||
PUSH encode_txn
|
||||
@ -96,6 +107,12 @@ global encode_receipt:
|
||||
|
||||
global encode_storage_value:
|
||||
// stack: rlp_pos, value_ptr, retdest
|
||||
SWAP1 %mload_trie_data SWAP1
|
||||
// stack: rlp_pos, value, retdest
|
||||
// The YP says storage trie is a map "... to the RLP-encoded 256-bit integer values"
|
||||
// which seems to imply that this should be %encode_rlp_256. But %encode_rlp_scalar
|
||||
// causes the tests to pass, so it seems storage values should be treated as variable-
|
||||
// length after all.
|
||||
%encode_rlp_scalar
|
||||
// stack: rlp_pos', retdest
|
||||
SWAP1
|
||||
|
||||
@ -10,6 +10,23 @@
|
||||
// stack: (empty)
|
||||
%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(0x10000)
|
||||
// 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)
|
||||
|
||||
@ -196,66 +196,65 @@ encode_rlp_list_prefix_large_done_writing_len:
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
// Given an RLP list payload which starts at position 9 and ends at the given
|
||||
// position, prepend the appropriate RLP list prefix. Returns the updated start
|
||||
// position, as well as the length of the RLP data (including the newly-added
|
||||
// prefix).
|
||||
// Given an RLP list payload which starts and ends at the given positions,
|
||||
// prepend the appropriate RLP list prefix. Returns the updated start position,
|
||||
// as well as the length of the RLP data (including the newly-added prefix).
|
||||
//
|
||||
// (We sometimes start list payloads at position 9 because 9 is the length of
|
||||
// the longest possible RLP list prefix.)
|
||||
//
|
||||
// Pre stack: end_pos, retdest
|
||||
// Post stack: start_pos, rlp_len
|
||||
// Pre stack: end_pos, start_pos, retdest
|
||||
// Post stack: prefix_start_pos, rlp_len
|
||||
global prepend_rlp_list_prefix:
|
||||
// stack: end_pos, retdest
|
||||
// Since the list payload starts at position 9, payload_len = end_pos - 9.
|
||||
PUSH 9 DUP2 SUB
|
||||
// stack: payload_len, end_pos, retdest
|
||||
// stack: end_pos, start_pos, retdest
|
||||
DUP2 DUP2 SUB // end_pos - start_pos
|
||||
// stack: payload_len, end_pos, start_pos, retdest
|
||||
DUP1 %gt_const(55)
|
||||
%jumpi(prepend_rlp_list_prefix_big)
|
||||
|
||||
// If we got here, we have a small list, so we prepend 0xc0 + len at position 8.
|
||||
// stack: payload_len, end_pos, retdest
|
||||
%add_const(0xc0)
|
||||
// stack: prefix_byte, end_pos, retdest
|
||||
PUSH 8 // offset
|
||||
// stack: payload_len, end_pos, start_pos, retdest
|
||||
DUP1 %add_const(0xc0)
|
||||
// stack: prefix_byte, payload_len, end_pos, start_pos, retdest
|
||||
DUP4 %decrement // offset of prefix
|
||||
%mstore_rlp
|
||||
// stack: end_pos, retdest
|
||||
%sub_const(8)
|
||||
// stack: rlp_len, retdest
|
||||
PUSH 8 // start_pos
|
||||
%stack (start_pos, rlp_len, retdest) -> (retdest, start_pos, rlp_len)
|
||||
// stack: payload_len, end_pos, start_pos, retdest
|
||||
%increment
|
||||
// stack: rlp_len, end_pos, start_pos, retdest
|
||||
SWAP2 %decrement
|
||||
// stack: prefix_start_pos, end_pos, rlp_len, retdest
|
||||
%stack (prefix_start_pos, end_pos, rlp_len, retdest) -> (retdest, prefix_start_pos, rlp_len)
|
||||
JUMP
|
||||
|
||||
prepend_rlp_list_prefix_big:
|
||||
// We have a large list, so we prepend 0xf7 + len_of_len at position
|
||||
// 8 - len_of_len, followed by the length itself.
|
||||
// stack: payload_len, end_pos, retdest
|
||||
// prefix_start_pos = start_pos - 1 - len_of_len
|
||||
// followed by the length itself.
|
||||
// stack: payload_len, end_pos, start_pos, retdest
|
||||
DUP1 %num_bytes
|
||||
// stack: len_of_len, payload_len, end_pos, retdest
|
||||
// stack: len_of_len, payload_len, end_pos, start_pos, retdest
|
||||
DUP1
|
||||
PUSH 8
|
||||
DUP5 %decrement // start_pos - 1
|
||||
SUB
|
||||
// stack: start_pos, len_of_len, payload_len, end_pos, retdest
|
||||
DUP2 %add_const(0xf7) DUP2 %mstore_rlp // rlp[start_pos] = 0xf7 + len_of_len
|
||||
DUP1 %increment // start_len_pos = start_pos + 1
|
||||
%stack (start_len_pos, start_pos, len_of_len, payload_len, end_pos, retdest)
|
||||
// stack: prefix_start_pos, len_of_len, payload_len, end_pos, start_pos, retdest
|
||||
DUP2 %add_const(0xf7) DUP2 %mstore_rlp // rlp[prefix_start_pos] = 0xf7 + len_of_len
|
||||
// stack: prefix_start_pos, len_of_len, payload_len, end_pos, start_pos, retdest
|
||||
DUP1 %increment // start_len_pos = prefix_start_pos + 1
|
||||
%stack (start_len_pos, prefix_start_pos, len_of_len, payload_len, end_pos, start_pos, retdest)
|
||||
-> (start_len_pos, payload_len, len_of_len,
|
||||
prepend_rlp_list_prefix_big_done_writing_len,
|
||||
start_pos, end_pos, retdest)
|
||||
prefix_start_pos, end_pos, retdest)
|
||||
%jump(mstore_unpacking_rlp)
|
||||
prepend_rlp_list_prefix_big_done_writing_len:
|
||||
// stack: 9, start_pos, end_pos, retdest
|
||||
%stack (_9, start_pos, end_pos) -> (end_pos, start_pos, start_pos)
|
||||
// stack: end_pos, start_pos, start_pos, retdest
|
||||
// stack: start_pos, prefix_start_pos, end_pos, retdest
|
||||
%stack (start_pos, prefix_start_pos, end_pos)
|
||||
-> (end_pos, prefix_start_pos, prefix_start_pos)
|
||||
// stack: end_pos, prefix_start_pos, prefix_start_pos, retdest
|
||||
SUB
|
||||
// stack: rlp_len, start_pos, retdest
|
||||
%stack (rlp_len, start_pos, retdest) -> (retdest, start_pos, rlp_len)
|
||||
// stack: rlp_len, prefix_start_pos, retdest
|
||||
%stack (rlp_len, prefix_start_pos, retdest) -> (retdest, prefix_start_pos, rlp_len)
|
||||
JUMP
|
||||
|
||||
// Convenience macro to call prepend_rlp_list_prefix and return where we left off.
|
||||
%macro prepend_rlp_list_prefix
|
||||
%stack (end_pos) -> (end_pos, %%after)
|
||||
%stack (end_pos, start_pos) -> (end_pos, start_pos, %%after)
|
||||
%jump(prepend_rlp_list_prefix)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
@ -84,62 +84,64 @@ type_0_compute_signed_data:
|
||||
// otherwise, it is
|
||||
// keccak256(rlp([nonce, gas_price, gas_limit, to, value, data]))
|
||||
|
||||
%alloc_rlp_block
|
||||
// stack: rlp_start, retdest
|
||||
%mload_txn_field(@TXN_FIELD_NONCE)
|
||||
// stack: nonce, retdest
|
||||
PUSH 9 // We start at 9 to leave room to prepend the largest possible RLP list header.
|
||||
// stack: rlp_pos, nonce, retdest
|
||||
// stack: nonce, rlp_start, retdest
|
||||
DUP2
|
||||
// stack: rlp_pos, nonce, rlp_start, retdest
|
||||
%encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_TO)
|
||||
SWAP1 %encode_rlp_160
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
// Encode txn data.
|
||||
%mload_txn_field(@TXN_FIELD_DATA_LEN)
|
||||
PUSH 0 // ADDR.virt
|
||||
PUSH @SEGMENT_TXN_DATA
|
||||
PUSH 0 // ADDR.context
|
||||
// stack: ADDR: 3, len, rlp_pos, retdest
|
||||
// stack: ADDR: 3, len, rlp_pos, rlp_start, retdest
|
||||
PUSH after_serializing_txn_data
|
||||
// stack: after_serializing_txn_data, ADDR: 3, len, rlp_pos, retdest
|
||||
// stack: after_serializing_txn_data, ADDR: 3, len, rlp_pos, rlp_start, retdest
|
||||
SWAP5
|
||||
// stack: rlp_pos, ADDR: 3, len, after_serializing_txn_data, retdest
|
||||
// stack: rlp_pos, ADDR: 3, len, after_serializing_txn_data, rlp_start, retdest
|
||||
%jump(encode_rlp_string)
|
||||
|
||||
after_serializing_txn_data:
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
%mload_txn_field(@TXN_FIELD_CHAIN_ID_PRESENT)
|
||||
ISZERO %jumpi(finish_rlp_list)
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
PUSH 0
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
PUSH 0
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, retdest
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
finish_rlp_list:
|
||||
%prepend_rlp_list_prefix
|
||||
// stack: start_pos, rlp_len, retdest
|
||||
// stack: prefix_start_pos, rlp_len, retdest
|
||||
PUSH @SEGMENT_RLP_RAW
|
||||
PUSH 0 // context
|
||||
// stack: ADDR: 3, rlp_len, retdest
|
||||
|
||||
@ -6,10 +6,13 @@ pub(crate) enum GlobalMetadata {
|
||||
/// give each new context a unique ID, so that its memory will be zero-initialized.
|
||||
LargestContext = 0,
|
||||
/// The size of active memory, in bytes.
|
||||
MemorySize = 2,
|
||||
MemorySize = 1,
|
||||
/// The size of the `TrieData` segment, in bytes. In other words, the next address available for
|
||||
/// appending additional trie data.
|
||||
TrieDataSize = 3,
|
||||
TrieDataSize = 2,
|
||||
/// The size of the `TrieData` segment, in bytes. In other words, the next address available for
|
||||
/// appending additional trie data.
|
||||
RlpDataSize = 3,
|
||||
/// A pointer to the root of the state trie within the `TrieData` buffer.
|
||||
StateTrieRoot = 4,
|
||||
/// A pointer to the root of the transaction trie within the `TrieData` buffer.
|
||||
@ -45,13 +48,14 @@ pub(crate) enum GlobalMetadata {
|
||||
}
|
||||
|
||||
impl GlobalMetadata {
|
||||
pub(crate) const COUNT: usize = 21;
|
||||
pub(crate) const COUNT: usize = 22;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
Self::LargestContext,
|
||||
Self::MemorySize,
|
||||
Self::TrieDataSize,
|
||||
Self::RlpDataSize,
|
||||
Self::StateTrieRoot,
|
||||
Self::TransactionTrieRoot,
|
||||
Self::ReceiptTrieRoot,
|
||||
@ -79,6 +83,7 @@ impl GlobalMetadata {
|
||||
Self::LargestContext => "GLOBAL_METADATA_LARGEST_CONTEXT",
|
||||
Self::MemorySize => "GLOBAL_METADATA_MEMORY_SIZE",
|
||||
Self::TrieDataSize => "GLOBAL_METADATA_TRIE_DATA_SIZE",
|
||||
Self::RlpDataSize => "GLOBAL_METADATA_RLP_DATA_SIZE",
|
||||
Self::StateTrieRoot => "GLOBAL_METADATA_STATE_TRIE_ROOT",
|
||||
Self::TransactionTrieRoot => "GLOBAL_METADATA_TXN_TRIE_ROOT",
|
||||
Self::ReceiptTrieRoot => "GLOBAL_METADATA_RECEIPT_TRIE_ROOT",
|
||||
|
||||
@ -279,6 +279,7 @@ impl<'a> Interpreter<'a> {
|
||||
.byte(0);
|
||||
self.opcode_count[opcode as usize] += 1;
|
||||
self.incr(1);
|
||||
|
||||
match opcode {
|
||||
0x00 => self.run_stop(), // "STOP",
|
||||
0x01 => self.run_add(), // "ADD",
|
||||
@ -356,7 +357,7 @@ impl<'a> Interpreter<'a> {
|
||||
0xa2 => todo!(), // "LOG2",
|
||||
0xa3 => todo!(), // "LOG3",
|
||||
0xa4 => todo!(), // "LOG4",
|
||||
0xa5 => bail!("Executed PANIC"), // "PANIC",
|
||||
0xa5 => bail!("Executed PANIC, stack={:?}", self.stack()), // "PANIC",
|
||||
0xf0 => todo!(), // "CREATE",
|
||||
0xf1 => todo!(), // "CALL",
|
||||
0xf2 => todo!(), // "CALLCODE",
|
||||
|
||||
@ -7,7 +7,7 @@ use crate::memory::segments::Segment;
|
||||
|
||||
#[test]
|
||||
fn test_mload_packing_1_byte() -> Result<()> {
|
||||
let mstore_unpacking = KERNEL.global_labels["mload_packing"];
|
||||
let mload_packing = KERNEL.global_labels["mload_packing"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let len = 1.into();
|
||||
@ -16,7 +16,7 @@ fn test_mload_packing_1_byte() -> Result<()> {
|
||||
let context = 0.into();
|
||||
let initial_stack = vec![retdest, len, offset, segment, context];
|
||||
|
||||
let mut interpreter = Interpreter::new_with_kernel(mstore_unpacking, initial_stack);
|
||||
let mut interpreter = Interpreter::new_with_kernel(mload_packing, initial_stack);
|
||||
interpreter.set_rlp_memory(vec![0, 0, 0xAB]);
|
||||
|
||||
interpreter.run()?;
|
||||
@ -27,7 +27,7 @@ fn test_mload_packing_1_byte() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn test_mload_packing_3_bytes() -> Result<()> {
|
||||
let mstore_unpacking = KERNEL.global_labels["mload_packing"];
|
||||
let mload_packing = KERNEL.global_labels["mload_packing"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let len = 3.into();
|
||||
@ -36,7 +36,7 @@ fn test_mload_packing_3_bytes() -> Result<()> {
|
||||
let context = 0.into();
|
||||
let initial_stack = vec![retdest, len, offset, segment, context];
|
||||
|
||||
let mut interpreter = Interpreter::new_with_kernel(mstore_unpacking, initial_stack);
|
||||
let mut interpreter = Interpreter::new_with_kernel(mload_packing, initial_stack);
|
||||
interpreter.set_rlp_memory(vec![0, 0, 0xAB, 0xCD, 0xEF]);
|
||||
|
||||
interpreter.run()?;
|
||||
@ -47,7 +47,7 @@ fn test_mload_packing_3_bytes() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn test_mload_packing_32_bytes() -> Result<()> {
|
||||
let mstore_unpacking = KERNEL.global_labels["mload_packing"];
|
||||
let mload_packing = KERNEL.global_labels["mload_packing"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let len = 32.into();
|
||||
@ -56,7 +56,7 @@ fn test_mload_packing_32_bytes() -> Result<()> {
|
||||
let context = 0.into();
|
||||
let initial_stack = vec![retdest, len, offset, segment, context];
|
||||
|
||||
let mut interpreter = Interpreter::new_with_kernel(mstore_unpacking, initial_stack);
|
||||
let mut interpreter = Interpreter::new_with_kernel(mload_packing, initial_stack);
|
||||
interpreter.set_rlp_memory(vec![0xFF; 32]);
|
||||
|
||||
interpreter.run()?;
|
||||
|
||||
@ -86,8 +86,9 @@ fn test_prepend_rlp_list_prefix_small() -> Result<()> {
|
||||
let prepend_rlp_list_prefix = KERNEL.global_labels["prepend_rlp_list_prefix"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let start_pos = 9.into();
|
||||
let end_pos = (9 + 5).into();
|
||||
let initial_stack = vec![retdest, end_pos];
|
||||
let initial_stack = vec![retdest, start_pos, end_pos];
|
||||
let mut interpreter = Interpreter::new_with_kernel(prepend_rlp_list_prefix, initial_stack);
|
||||
interpreter.set_rlp_memory(vec![
|
||||
// Nine 0s to leave room for the longest possible RLP list prefix.
|
||||
@ -114,8 +115,9 @@ fn test_prepend_rlp_list_prefix_large() -> Result<()> {
|
||||
let prepend_rlp_list_prefix = KERNEL.global_labels["prepend_rlp_list_prefix"];
|
||||
|
||||
let retdest = 0xDEADBEEFu32.into();
|
||||
let start_pos = 9.into();
|
||||
let end_pos = (9 + 60).into();
|
||||
let initial_stack = vec![retdest, end_pos];
|
||||
let initial_stack = vec![retdest, start_pos, end_pos];
|
||||
let mut interpreter = Interpreter::new_with_kernel(prepend_rlp_list_prefix, initial_stack);
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
||||
139
evm/tests/add11_yml.rs
Normal file
139
evm/tests/add11_yml.rs
Normal file
@ -0,0 +1,139 @@
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV};
|
||||
use eth_trie_utils::partial_trie::{Nibbles, PartialTrie};
|
||||
use ethereum_types::Address;
|
||||
use hex_literal::hex;
|
||||
use keccak_hash::keccak;
|
||||
use plonky2::field::goldilocks_field::GoldilocksField;
|
||||
use plonky2::plonk::config::PoseidonGoldilocksConfig;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2_evm::all_stark::AllStark;
|
||||
use plonky2_evm::config::StarkConfig;
|
||||
use plonky2_evm::generation::mpt::AccountRlp;
|
||||
use plonky2_evm::generation::{GenerationInputs, TrieInputs};
|
||||
use plonky2_evm::proof::BlockMetadata;
|
||||
use plonky2_evm::prover::prove;
|
||||
use plonky2_evm::verifier::verify_proof;
|
||||
|
||||
type F = GoldilocksField;
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
|
||||
/// Test a simple token transfer to a new address.
|
||||
#[test]
|
||||
fn add11_yml() -> anyhow::Result<()> {
|
||||
init_logger();
|
||||
|
||||
let all_stark = AllStark::<F, D>::default();
|
||||
let config = StarkConfig::standard_fast_config();
|
||||
|
||||
let beneficiary = hex!("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba");
|
||||
let sender = hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b");
|
||||
let to = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87");
|
||||
|
||||
let beneficiary_state_key = keccak(beneficiary);
|
||||
let sender_state_key = keccak(sender);
|
||||
let to_state_key = keccak(to);
|
||||
|
||||
let beneficiary_nibbles = Nibbles::from_bytes_be(beneficiary_state_key.as_bytes()).unwrap();
|
||||
let sender_nibbles = Nibbles::from_bytes_be(sender_state_key.as_bytes()).unwrap();
|
||||
let to_nibbles = Nibbles::from_bytes_be(to_state_key.as_bytes()).unwrap();
|
||||
|
||||
let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00];
|
||||
let code_hash = keccak(code);
|
||||
|
||||
let beneficiary_account_before = AccountRlp {
|
||||
nonce: 1.into(),
|
||||
..AccountRlp::default()
|
||||
};
|
||||
let sender_account_before = AccountRlp {
|
||||
balance: 0x0de0b6b3a7640000u64.into(),
|
||||
..AccountRlp::default()
|
||||
};
|
||||
let to_account_before = AccountRlp {
|
||||
balance: 0x0de0b6b3a7640000u64.into(),
|
||||
code_hash,
|
||||
..AccountRlp::default()
|
||||
};
|
||||
|
||||
let mut state_trie_before = PartialTrie::Empty;
|
||||
state_trie_before.insert(
|
||||
beneficiary_nibbles,
|
||||
rlp::encode(&beneficiary_account_before).to_vec(),
|
||||
);
|
||||
state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec());
|
||||
state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec());
|
||||
|
||||
let tries_before = TrieInputs {
|
||||
state_trie: state_trie_before,
|
||||
transactions_trie: PartialTrie::Empty,
|
||||
receipts_trie: PartialTrie::Empty,
|
||||
storage_tries: vec![(Address::from_slice(&to), PartialTrie::Empty)],
|
||||
};
|
||||
|
||||
let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16");
|
||||
|
||||
let block_metadata = BlockMetadata {
|
||||
block_beneficiary: Address::from(beneficiary),
|
||||
block_base_fee: 0xa.into(),
|
||||
..BlockMetadata::default()
|
||||
};
|
||||
|
||||
let mut contract_code = HashMap::new();
|
||||
contract_code.insert(keccak(vec![]), vec![]);
|
||||
contract_code.insert(code_hash, code.to_vec());
|
||||
|
||||
let inputs = GenerationInputs {
|
||||
signed_txns: vec![txn.to_vec()],
|
||||
tries: tries_before,
|
||||
contract_code,
|
||||
block_metadata,
|
||||
addresses: vec![],
|
||||
};
|
||||
|
||||
let mut timing = TimingTree::new("prove", log::Level::Debug);
|
||||
let proof = prove::<F, C, D>(&all_stark, &config, inputs, &mut timing)?;
|
||||
timing.filter(Duration::from_millis(100)).print();
|
||||
|
||||
let beneficiary_account_after = AccountRlp {
|
||||
nonce: 1.into(),
|
||||
..AccountRlp::default()
|
||||
};
|
||||
let sender_account_after = AccountRlp {
|
||||
balance: 0xde0b6b3a75be550u64.into(),
|
||||
nonce: 1.into(),
|
||||
..AccountRlp::default()
|
||||
};
|
||||
let to_account_after = AccountRlp {
|
||||
balance: 0xde0b6b3a76586a0u64.into(),
|
||||
code_hash,
|
||||
// Storage map: { 0 => 2 }
|
||||
storage_root: PartialTrie::Leaf {
|
||||
nibbles: Nibbles::from_h256_be(keccak([0u8; 32])),
|
||||
value: vec![2],
|
||||
}
|
||||
.calc_hash(),
|
||||
..AccountRlp::default()
|
||||
};
|
||||
|
||||
let mut expected_state_trie_after = PartialTrie::Empty;
|
||||
expected_state_trie_after.insert(
|
||||
beneficiary_nibbles,
|
||||
rlp::encode(&beneficiary_account_after).to_vec(),
|
||||
);
|
||||
expected_state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec());
|
||||
expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec());
|
||||
|
||||
assert_eq!(
|
||||
proof.public_values.trie_roots_after.state_root,
|
||||
expected_state_trie_after.calc_hash()
|
||||
);
|
||||
|
||||
verify_proof(&all_stark, proof, &config)
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user