Remove copy on write for mpt_insert and mpt_delete

This commit is contained in:
Linda Guiga 2023-08-15 13:21:50 +01:00
parent eb7bb46102
commit d70d67fad4
No known key found for this signature in database
5 changed files with 81 additions and 143 deletions

View File

@ -3,7 +3,6 @@
//
// Pre stack: node_ptr, num_nibbles, key, retdest
// Post stack: updated_node_ptr
// TODO: Optimize this by removing the copy-on-write logic.
global mpt_delete:
// stack: node_ptr, num_nibbles, key, retdest
DUP1 %mload_trie_data

View File

@ -27,37 +27,16 @@ after_mpt_delete_branch:
// If the updated child is empty, check if we need to normalize the branch node.
DUP1 %mload_trie_data ISZERO %jumpi(maybe_normalize_branch)
// Make a copy of the branch node and set `branch[first_nibble] = updated_child_ptr`.
// Set `branch[first_nibble] = updated_child_ptr`.
update_branch:
// stack: updated_child_ptr, first_nibble, node_payload_ptr, retdest
%get_trie_data_size
// stack: updated_branch_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
PUSH @MPT_NODE_BRANCH %append_to_trie_data
// stack: updated_branch_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
DUP4 %mload_trie_data %append_to_trie_data // Copy child[0]
DUP4 %add_const(1) %mload_trie_data %append_to_trie_data // ...
DUP4 %add_const(2) %mload_trie_data %append_to_trie_data
DUP4 %add_const(3) %mload_trie_data %append_to_trie_data
DUP4 %add_const(4) %mload_trie_data %append_to_trie_data
DUP4 %add_const(5) %mload_trie_data %append_to_trie_data
DUP4 %add_const(6) %mload_trie_data %append_to_trie_data
DUP4 %add_const(7) %mload_trie_data %append_to_trie_data
DUP4 %add_const(8) %mload_trie_data %append_to_trie_data
DUP4 %add_const(9) %mload_trie_data %append_to_trie_data
DUP4 %add_const(10) %mload_trie_data %append_to_trie_data
DUP4 %add_const(11) %mload_trie_data %append_to_trie_data
DUP4 %add_const(12) %mload_trie_data %append_to_trie_data
DUP4 %add_const(13) %mload_trie_data %append_to_trie_data
DUP4 %add_const(14) %mload_trie_data %append_to_trie_data
DUP4 %add_const(15) %mload_trie_data %append_to_trie_data // Copy child[15]
DUP4 %add_const(16) %mload_trie_data %append_to_trie_data // Copy value_ptr
// stack: updated_branch_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
SWAP1
// stack: updated_child_ptr, updated_branch_ptr, first_nibble, node_payload_ptr, retdest
DUP2 %increment DUP4 ADD
// stack: updated_branch_ptr+first_nibble+1, updated_child_ptr, updated_branch_ptr, first_nibble, node_payload_ptr, retdest
DUP3 DUP3 ADD
// stack: node_payload_ptr+first_nibble, updated_child_ptr, first_nibble, node_payload_ptr, retdest
%mstore_trie_data
%stack (updated_branch_ptr, first_nibble, node_payload_ptr, retdest) -> (retdest, updated_branch_ptr)
%stack (first_nibble, node_payload_ptr, retdest) -> (node_payload_ptr, retdest)
PUSH 1 SWAP1 SUB
// stack: node_ptr, retdest
SWAP1
JUMP
// The updated child is empty. Count how many non-empty children the branch node has.
@ -121,31 +100,24 @@ maybe_normalize_branch_branch:
// The only child of the branch node is a leaf/extension node.
// Transform the branch node into an leaf/extension node of length 1+len(child).
// For that, return the modified child as the new node.
maybe_normalize_branch_leafext:
// stack: only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
DUP1 %mload_trie_data
// stack: child_type, only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
DUP2 %increment %mload_trie_data
// stack: child_len, child_type, only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
DUP3 %add_const(2) %mload_trie_data
// stack: child_key, child_len, child_type, only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
SWAP3 %add_const(3) %mload_trie_data
// stack: child_value_ptr, child_len, child_type, child_key, updated_child_ptr, first_nibble, node_payload_ptr, retdest
DUP1 %increment %mload_trie_data
// stack: child_len, only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
DUP2 %add_const(2) %mload_trie_data
// stack: child_key, child_len, only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr, retdest
%mload_kernel_general(1)
%stack (i, child_value_ptr, child_len, child_type, child_key, updated_child_ptr, first_nibble, node_payload_ptr) ->
(1, i, child_len, child_key, child_type, child_value_ptr)
%stack (i, child_key, child_len, only_child_ptr, updated_child_ptr, first_nibble, node_payload_ptr) ->
(1, i, child_len, child_key, only_child_ptr)
%merge_nibbles
// stack: len, key, child_type, value_ptr, retdest
%get_trie_data_size // pointer to the leaf/extension node we're about to create
// stack: node_ptr, len, key, child_type, value_ptr, retdest
SWAP3
// stack: child_type, len, key, node_ptr, value_ptr, retdest
%append_to_trie_data // Append type to our node
// stack: len, key, node_ptr, value_ptr, retdest
%append_to_trie_data // Append len to our node
// stack: key, node_ptr, value_ptr, retdest
%append_to_trie_data // Append key to our node
// stack: node_ptr, value_ptr, retdest
SWAP1 %append_to_trie_data // Append value_ptr to our node
// stack: len, key, only_child_ptr,retdest
DUP3
// stack: node_ptr, len, key, only_child_ptr, retdest
SWAP1 DUP2
// stack: node_ptr, len, node_ptr, key, only_child_ptr, retdest
%increment %mstore_trie_data // Change len in the child node
// stack: node_ptr, key, only_child_ptr, retdest
%add_const(2) %mstore_trie_data // Change key in the child node
// stack: node_ptr, retdest
SWAP1 JUMP

View File

@ -18,15 +18,15 @@ global mpt_delete_extension:
// stack: num_nibbles, key, node_payload_ptr, node_len, node_key, retdest
SWAP2
// stack: node_payload_ptr, key, num_nibbles, node_len, node_key, retdest
%add_const(2) %mload_trie_data
%stack (node_child_ptr, key, num_nibbles, node_len, node_key, retdest) ->
(node_child_ptr, num_nibbles, key, after_mpt_delete_extension, node_len, node_key, retdest)
DUP1 %add_const(2) %mload_trie_data
%stack (node_child_ptr, node_payload_ptr, key, num_nibbles, node_len, node_key, retdest) ->
(node_child_ptr, num_nibbles, key, after_mpt_delete_extension, node_payload_ptr, node_len, node_key, retdest)
%jump(mpt_delete)
after_mpt_delete_extension:
// stack: updated_child_node_ptr, node_len, node_key, retdest
// stack: updated_child_node_ptr, node_payload_ptr, node_len, node_key, retdest
DUP1 %mload_trie_data
// stack: child_type, updated_child_node_ptr, node_len, node_key, retdest
// stack: child_type, updated_child_node_ptr, node_payload_ptr, node_len, node_key, retdest
DUP1 %eq_const(@MPT_NODE_BRANCH) %jumpi(after_mpt_delete_extension_branch)
DUP1 %eq_const(@MPT_NODE_EXTENSION) %jumpi(after_mpt_delete_extension_extension)
DUP1 %eq_const(@MPT_NODE_LEAF) %jumpi(after_mpt_delete_extension_leaf)
@ -34,66 +34,54 @@ after_mpt_delete_extension:
PANIC
after_mpt_delete_extension_branch:
// stack: child_type, updated_child_node_ptr, node_len, node_key, retdest
// stack: child_type, updated_child_node_ptr, node_payload_ptr, node_len, node_key, retdest
POP
// stack: updated_child_node_ptr, node_len, node_key, retdest
%get_trie_data_size // pointer to the extension node we're about to create
// stack: updated_child_node_ptr, node_payload_ptr, node_len, node_key, retdest
SWAP1
// stack: extension_ptr, updated_child_node_ptr, node_len, node_key, retdest
PUSH @MPT_NODE_EXTENSION %append_to_trie_data
PUSH @MPT_NODE_EXTENSION DUP2 %mstore_trie_data
// stack: extension_ptr, updated_child_node_ptr, node_len, node_key, retdest
SWAP2 %append_to_trie_data // Append node_len to our node
// stack: updated_child_node_ptr, extension_ptr, node_key, retdest
SWAP2 %append_to_trie_data // Append node_key to our node
// stack: extension_ptr, updated_child_node_ptr, retdest
SWAP1 %append_to_trie_data // Append updated_child_node_ptr to our node
DUP3 DUP2 %mstore_trie_data // Append node_len to our node
// stack: extension_ptr, updated_child_node_ptr, node_len, node_key, retdest
DUP4 DUP2 %mstore_trie_data // Append node_key to our node
// stack: extension_ptr, updated_child_node_ptr, node_len, node_key, retdest
SWAP1 DUP2 %mstore_trie_data // Append updated_child_node_ptr to our node
// stack: extension_ptr, node_len, node_key, retdest
%stack (extension_ptr, node_len, node_key, retdest) -> (retdest, extension_ptr)
// stack: extension_ptr, retdest
SWAP1 JUMP
JUMP
after_mpt_delete_extension_extension:
// stack: child_type, updated_child_node_ptr, node_len, node_key, retdest
POP
// stack: child_type, updated_child_node_ptr, node_payload_ptr, node_len, node_key, retdest
POP SWAP1 POP
// stack: updated_child_node_ptr, node_len, node_key, retdest
DUP1 %increment %mload_trie_data
// stack: child_len, updated_child_node_ptr, node_len, node_key, retdest
DUP2 %add_const(2) %mload_trie_data
// stack: child_key, child_len, updated_child_node_ptr, node_len, node_key, retdest
SWAP2 %add_const(3) %mload_trie_data
%stack (grandchild_ptr, child_len, child_key, node_len, node_key) -> (node_len, node_key, child_len, child_key, grandchild_ptr)
%stack (child_key, child_len, updated_child_node_ptr, node_len, node_key) -> (node_len, node_key, child_len, child_key, updated_child_node_ptr)
%merge_nibbles
// stack: len, key, grandchild_ptr, retdest
%get_trie_data_size // pointer to the extension node we're about to create
// stack: extension_ptr, len, key, grandchild_ptr, retdest
PUSH @MPT_NODE_EXTENSION %append_to_trie_data
// stack: extension_ptr, len, key, grandchild_ptr, retdest
SWAP1 %append_to_trie_data // Append len to our node
// stack: extension_ptr, key, grandchild_ptr, retdest
SWAP1 %append_to_trie_data // Append key to our node
// stack: extension_ptr, grandchild_ptr, retdest
SWAP1 %append_to_trie_data // Append grandchild_ptr to our node
// stack: len, key, updated_child_node_ptr, retdest
DUP3 %increment %mstore_trie_data // Change len
// stack: key, updated_child_node_ptr, retdest
DUP2 %add_const(2) %mstore_trie_data // Change key
// stack: extension_ptr, retdest
SWAP1 JUMP
// Essentially the same as `after_mpt_delete_extension_extension`. TODO: Could merge in a macro or common function.
after_mpt_delete_extension_leaf:
// stack: child_type, updated_child_node_ptr, node_len, node_key, retdest
POP
// stack: child_type, updated_child_node_ptr, node_payload_ptr, node_len, node_key, retdest
POP SWAP1 POP
// stack: updated_child_node_ptr, node_len, node_key, retdest
DUP1 %increment %mload_trie_data
// stack: child_len, updated_child_node_ptr, node_len, node_key, retdest
DUP2 %add_const(2) %mload_trie_data
// stack: child_key, child_len, updated_child_node_ptr, node_len, node_key, retdest
SWAP2 %add_const(3) %mload_trie_data
%stack (value_ptr, child_len, child_key, node_len, node_key) -> (node_len, node_key, child_len, child_key, value_ptr)
%stack (child_key, child_len, updated_child_node_ptr, node_len, node_key) -> (node_len, node_key, child_len, child_key, updated_child_node_ptr)
%merge_nibbles
// stack: len, key, value_ptr, retdest
%get_trie_data_size // pointer to the leaf node we're about to create
// stack: leaf_ptr, len, key, value_ptr, retdest
PUSH @MPT_NODE_LEAF %append_to_trie_data
// stack: leaf_ptr, len, key, value_ptr, retdest
SWAP1 %append_to_trie_data // Append len to our node
// stack: leaf_ptr, key, value_ptr, retdest
SWAP1 %append_to_trie_data // Append key to our node
// stack: leaf_ptr, value_ptr, retdest
SWAP1 %append_to_trie_data // Append value_ptr to our node
// stack: leaf_ptr, retdest
// stack: len, key, updated_child_node_ptr, retdest
DUP3 %increment %mstore_trie_data // Change len
// stack: key, updated_child_node_ptr, retdest
DUP2 %add_const(2) %mstore_trie_data // Change key
// stack: updated_child_node_ptr, retdest
SWAP1 JUMP

View File

@ -2,7 +2,6 @@
//
// Pre stack: node_ptr, num_nibbles, key, value_ptr, retdest
// Post stack: updated_node_ptr
// TODO: Optimize this by removing the copy-on-write logic.
global mpt_insert:
// stack: node_ptr, num_nibbles, key, value_ptr, retdest
DUP1 %mload_trie_data
@ -41,59 +40,40 @@ mpt_insert_empty:
mpt_insert_branch:
// stack: node_type, node_payload_ptr, num_nibbles, key, value_ptr, retdest
%get_trie_data_size
// stack: updated_branch_ptr, node_type, node_payload_ptr, num_nibbles, key, value_ptr, retdest
SWAP1
%append_to_trie_data
// stack: updated_branch_ptr, node_payload_ptr, num_nibbles, key, value_ptr, retdest
SWAP1
// stack: node_payload_ptr, updated_branch_ptr, num_nibbles, key, value_ptr, retdest
POP
// Copy the original node's data to our updated node.
DUP1 %mload_trie_data %append_to_trie_data // Copy child[0]
DUP1 %add_const(1) %mload_trie_data %append_to_trie_data // ...
DUP1 %add_const(2) %mload_trie_data %append_to_trie_data
DUP1 %add_const(3) %mload_trie_data %append_to_trie_data
DUP1 %add_const(4) %mload_trie_data %append_to_trie_data
DUP1 %add_const(5) %mload_trie_data %append_to_trie_data
DUP1 %add_const(6) %mload_trie_data %append_to_trie_data
DUP1 %add_const(7) %mload_trie_data %append_to_trie_data
DUP1 %add_const(8) %mload_trie_data %append_to_trie_data
DUP1 %add_const(9) %mload_trie_data %append_to_trie_data
DUP1 %add_const(10) %mload_trie_data %append_to_trie_data
DUP1 %add_const(11) %mload_trie_data %append_to_trie_data
DUP1 %add_const(12) %mload_trie_data %append_to_trie_data
DUP1 %add_const(13) %mload_trie_data %append_to_trie_data
DUP1 %add_const(14) %mload_trie_data %append_to_trie_data
DUP1 %add_const(15) %mload_trie_data %append_to_trie_data // Copy child[15]
%add_const(16) %mload_trie_data %append_to_trie_data // Copy value_ptr
//stack: node_payload_ptr, num_nibbles, key, value_ptr, retdest
// At this point, we branch based on whether the key terminates with this branch node.
// stack: updated_branch_ptr, num_nibbles, key, value_ptr, retdest
// stack: node_payload_ptr, num_nibbles, key, value_ptr, retdest
DUP2 %jumpi(mpt_insert_branch_nonterminal)
// The key terminates here, so the value will be placed right in our (updated) branch node.
// stack: updated_branch_ptr, num_nibbles, key, value_ptr, retdest
// stack: node_payload_ptr, num_nibbles, key, value_ptr, retdest
SWAP3
// stack: value_ptr, num_nibbles, key, updated_branch_ptr, retdest
DUP4 %add_const(17)
// stack: updated_branch_value_ptr_ptr, value_ptr, num_nibbles, key, updated_branch_ptr, retdest
// stack: value_ptr, num_nibbles, key, node_payload_ptr, retdest
DUP4 %add_const(16)
// stack: branch_value_ptr_ptr, value_ptr, num_nibbles, key, node_payload_ptr, retdest
%mstore_trie_data
// stack: num_nibbles, key, updated_branch_ptr, retdest
// stack: num_nibbles, key, node_payload_ptr, retdest
%pop2
// stack: updated_branch_ptr, retdest
// stack: node_payload_ptr, retdest
PUSH 1 SWAP1 SUB
// stack: branch_ptr, retdest
SWAP1
JUMP
mpt_insert_branch_nonterminal:
// The key continues, so we split off the first (most significant) nibble,
// and recursively insert into the child associated with that nibble.
// stack: updated_branch_ptr, num_nibbles, key, value_ptr, retdest
%stack (updated_branch_ptr, num_nibbles, key) -> (num_nibbles, key, updated_branch_ptr)
// stack: node_payload_ptr, num_nibbles, key, value_ptr, retdest
%stack (node_payload_ptr, num_nibbles, key) -> (num_nibbles, key, node_payload_ptr)
%split_first_nibble
// stack: first_nibble, num_nibbles, key, updated_branch_ptr, value_ptr, retdest
DUP4 %increment ADD
// stack: child_ptr_ptr, num_nibbles, key, updated_branch_ptr, value_ptr, retdest
// stack: first_nibble, num_nibbles, key, node_payload_ptr, value_ptr, retdest
DUP4 ADD
// stack: child_ptr_ptr, num_nibbles, key, node_payload_ptr, value_ptr, retdest
// Replace node_payload_ptr with branch pointer
SWAP3 PUSH 1 SWAP1 SUB SWAP3
%stack (child_ptr_ptr, num_nibbles, key, updated_branch_ptr, value_ptr)
-> (child_ptr_ptr, num_nibbles, key, value_ptr,
mpt_insert_branch_nonterminal_after_recursion,

View File

@ -177,17 +177,16 @@ insert_key_continues:
%jump(maybe_add_extension_for_common_key)
keys_match:
// The keys match exactly, so we simply create a new leaf node with the new value.xs
// The keys match exactly, so we simply replace the leaf value with the new value.
// stack: node_len, node_key, insert_len, insert_key, node_payload_ptr, insert_value_ptr, retdest
%stack (node_len, node_key, insert_len, insert_key, node_payload_ptr, insert_value_ptr)
-> (node_len, node_key, insert_value_ptr)
// stack: common_len, common_key, insert_value_ptr, retdest
%get_trie_data_size // pointer to the leaf node we're about to create
// stack: updated_leaf_ptr, common_len, common_key, insert_value_ptr, retdest
PUSH @MPT_NODE_LEAF %append_to_trie_data
SWAP1 %append_to_trie_data // Append common_len to our leaf node
SWAP1 %append_to_trie_data // Append common_key to our leaf node
SWAP1 %append_to_trie_data // Append insert_value_ptr to our leaf node
// stack: updated_leaf_ptr, retdestx
-> (node_payload_ptr, node_len, node_key, insert_value_ptr)
// stack: node_payload_ptr, common_len, common_key, insert_value_ptr, retdest
DUP4 DUP2
%add_const(2)
%mstore_trie_data
%stack (node_payload_ptr, common_len, common_key, insert_value_ptr, retdest) -> (node_payload_ptr, retdest)
PUSH 1 SWAP1 SUB
// stack: leaf_ptr, retdest
SWAP1
JUMP