diff --git a/evm/src/cpu/kernel/asm/mpt/delete/delete.asm b/evm/src/cpu/kernel/asm/mpt/delete/delete.asm index 60d5451d..913ba1fc 100644 --- a/evm/src/cpu/kernel/asm/mpt/delete/delete.asm +++ b/evm/src/cpu/kernel/asm/mpt/delete/delete.asm @@ -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 diff --git a/evm/src/cpu/kernel/asm/mpt/delete/delete_branch.asm b/evm/src/cpu/kernel/asm/mpt/delete/delete_branch.asm index a88f3b60..69c97943 100644 --- a/evm/src/cpu/kernel/asm/mpt/delete/delete_branch.asm +++ b/evm/src/cpu/kernel/asm/mpt/delete/delete_branch.asm @@ -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, 1, retdest) + 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 diff --git a/evm/src/cpu/kernel/asm/mpt/delete/delete_extension.asm b/evm/src/cpu/kernel/asm/mpt/delete/delete_extension.asm index 40fb31ee..149b971d 100644 --- a/evm/src/cpu/kernel/asm/mpt/delete/delete_extension.asm +++ b/evm/src/cpu/kernel/asm/mpt/delete/delete_extension.asm @@ -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 diff --git a/evm/src/cpu/kernel/asm/mpt/insert/insert.asm b/evm/src/cpu/kernel/asm/mpt/insert/insert.asm index 43c5e4a8..34889a33 100644 --- a/evm/src/cpu/kernel/asm/mpt/insert/insert.asm +++ b/evm/src/cpu/kernel/asm/mpt/insert/insert.asm @@ -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, diff --git a/evm/src/cpu/kernel/asm/mpt/insert/insert_leaf.asm b/evm/src/cpu/kernel/asm/mpt/insert/insert_leaf.asm index 6afe2f14..72a014ce 100644 --- a/evm/src/cpu/kernel/asm/mpt/insert/insert_leaf.asm +++ b/evm/src/cpu/kernel/asm/mpt/insert/insert_leaf.asm @@ -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