Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce overhead in storage reads and fix stack descriptions #572

Merged
merged 2 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -364,17 +364,6 @@ store_initial_slots_end:
JUMP


%macro insert_slot
%stack (addr_key, key, ptr) -> (addr_key, key, ptr, %%after)
%jump(insert_slot)
%%after:
// stack: value_ptr
%endmacro

%macro insert_slot_no_return
%insert_slot
%endmacro

// Multiplies the value at the top of the stack, denoted by ptr/5, by 5
// and aborts if ptr/5 >= (mem[@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE] - @SEGMENT_STORAGE_LINKED_LIST)/5.
// This way, @SEGMENT_STORAGE_LINKED_LIST + 5*ptr/5 must be pointing to the beginning of a node.
Expand Down Expand Up @@ -550,18 +539,18 @@ slot_found_write_value:

/// Inserts the pair (address_key, storage_key) and payload pointer into the linked list if it is not already present,
/// or modifies its payload if it was already present.
/// Returns `payload_ptr` if the storage key was inserted, `original_ptr` if it was already present.
/// Returns `value` if the storage key was inserted, `old_value` if it was already present.
global insert_slot:
// stack: addr_key, key, payload_ptr, retdest
// stack: addr_key, key, value, retdest
PROVER_INPUT(linked_list::insert_slot)
// stack: pred_ptr/5, addr_key, key, payload_ptr, retdest
// stack: pred_ptr/5, addr_key, key, value, retdest
%get_valid_slot_ptr

// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest
DUP1
MLOAD_GENERAL
DUP1
// stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, value, retdest
DUP4
GT
DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST)
Expand All @@ -570,25 +559,25 @@ global insert_slot:
// node with key @U256_MAX (and hence we're inserting a new minimum), then
// we need to insert a new node.
%jumpi(insert_new_slot)
// stack: pred_addr_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_addr_key, pred_ptr, addr_key, key, value, retdest
// If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr.
DUP3
%assert_eq
// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest
DUP1
%increment
MLOAD_GENERAL
// stack: pred_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_key, pred_ptr, addr_key, key, value, retdest
DUP1 DUP5
GT
%jumpi(insert_new_slot)
// stack: pred_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_key, pred_ptr, addr_key, key, value, retdest
DUP4
// We know that key <= pred_key. It must hold that pred_key == key.
%assert_eq
// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest

// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest
// Check that this is not a deleted node
DUP1
%add_const(@STORAGE_NEXT_NODE_PTR)
Expand All @@ -599,112 +588,112 @@ global insert_slot:

slot_found_write:
// The slot was already in the list
// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// Load the the payload pointer and access counter
// stack: pred_ptr, addr_key, key, value, retdest
// Load the old value
%add_const(2)
DUP1
MLOAD_GENERAL
// stack: orig_payload_ptr, pred_ptr + 2, addr_key, key, payload_ptr, retdest
// stack: old_value, pred_ptr + 2, addr_key, key, value, retdest
SWAP1
DUP5
MSTORE_GENERAL // Store the new payload
%stack (orig_payload_ptr, addr_key, key, payload_ptr, retdest) -> (retdest, orig_payload_ptr)
MSTORE_GENERAL // Store the new value
%stack (old_value, addr_key, key, value, retdest) -> (retdest, old_value)
JUMP
insert_new_slot:
// stack: pred_addr or pred_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_addr or pred_key, pred_ptr, addr_key, key, value, retdest
POP
// get the value of the next address
%add_const(@STORAGE_NEXT_NODE_PTR)
// stack: next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_ptr_ptr, addr_key, key, value, retdest
%mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE)
DUP2
MLOAD_GENERAL
// stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
// Check that this is not a deleted node
DUP1
%eq_const(@U256_MAX)
%assert_zero
DUP1
MLOAD_GENERAL
// stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
DUP1
DUP6
// Here, (addr_key > pred_addr_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST).
// We should have (addr_key < next_addr_key), meaning the new value can be inserted between pred_ptr and next_ptr.
LT
%jumpi(next_node_ok)
// If addr_key <= next_addr_key, then it addr must be equal to next_addr
// stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
DUP5
%assert_eq
// stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
DUP1
%increment
MLOAD_GENERAL
// stack: next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
DUP1 // This is added just to have the correct stack in next_node_ok
DUP7
// The next key must be strictly larger
%assert_lt
next_node_ok:
// stack: next_addr or next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_addr or next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
POP
// stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, payload_ptr, retdest
// stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest
SWAP2
DUP2
// stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, key, payload_ptr, retdest
// stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, key, value, retdest
MSTORE_GENERAL
// stack: new_ptr, next_ptr, addr_key, key, payload_ptr, retdest
// stack: new_ptr, next_ptr, addr_key, key, value, retdest
// Write the address in the new node
DUP1
DUP4
MSTORE_GENERAL
// stack: new_ptr, next_ptr, addr_key, key, payload_ptr, retdest
// stack: new_ptr, next_ptr, addr_key, key, value, retdest
// Write the key in the new node
%increment
DUP1
DUP5
MSTORE_GENERAL
// stack: new_ptr + 1, next_ptr, addr_key, key, payload_ptr, retdest
// Store payload_ptr
// stack: new_ptr + 1, next_ptr, addr_key, key, value, retdest
// Store value
%increment
DUP1
DUP6
MSTORE_GENERAL

// stack: new_ptr + 2, next_ptr, addr_key, key, payload_ptr, retdest
// Store the copy of payload_ptr
// stack: new_ptr + 2, next_ptr, addr_key, key, value, retdest
// Store the copy of value
%increment
DUP1
DUP6
%clone_slot
MSTORE_GENERAL
// stack: new_ptr + 3, next_ptr, addr_key, key, payload_ptr, retdest
// stack: new_ptr + 3, next_ptr, addr_key, key, value, retdest
%increment
DUP1
// stack: new_next_ptr, new_next_ptr, next_ptr, addr_key, key, payload_ptr, retdest
// stack: new_next_ptr, new_next_ptr, next_ptr, addr_key, key, value, retdest
SWAP2
MSTORE_GENERAL
// stack: new_next_ptr, addr_key, key, payload_ptr, retdest
// stack: new_next_ptr, addr_key, key, value, retdest
%increment
%mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE)
// stack: addr_key, key, payload_ptr, retdest
%stack (addr_key, key, payload_ptr, retdest) -> (retdest, payload_ptr)
// stack: addr_key, key, value, retdest
%stack (addr_key, key, value, retdest) -> (retdest, value)
JUMP

/// Searches the pair (address_key, storage_key) in the storage the linked list.
/// Returns `payload_ptr` if the storage key was inserted, `original_ptr` if it was already present.
/// Returns `value` if the storage key was inserted, `old_value` if it was already present.
global search_slot:
// stack: addr_key, key, payload_ptr, retdest
// stack: addr_key, key, value, retdest
PROVER_INPUT(linked_list::insert_slot)
// stack: pred_ptr/5, addr_key, key, payload_ptr, retdest
// stack: pred_ptr/5, addr_key, key, value, retdest
%get_valid_slot_ptr

// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest
DUP1
MLOAD_GENERAL
DUP1
// stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, value, retdest
DUP4
GT
DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST)
Expand All @@ -713,25 +702,25 @@ global search_slot:
// node with key @U256_MAX (and hence we're inserting a new minimum), then
// the slot was not found
%jumpi(slot_not_found)
// stack: pred_addr_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_addr_key, pred_ptr, addr_key, key, value, retdest
// If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr.
DUP3
%assert_eq
// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest
DUP1
%increment
MLOAD_GENERAL
// stack: pred_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_key, pred_ptr, addr_key, key, value, retdest
DUP1 DUP5
GT
%jumpi(slot_not_found)
// stack: pred_key, pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_key, pred_ptr, addr_key, key, value, retdest
DUP4
// We know that key <= pred_key. It must hold that pred_key == key.
%assert_eq
// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest

// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// stack: pred_ptr, addr_key, key, value, retdest
// Check that this is not a deleted node
DUP1
%add_const(@STORAGE_NEXT_NODE_PTR)
Expand All @@ -740,27 +729,27 @@ global search_slot:
// The storage key is not in the list.
PANIC
slot_not_found:
// stack: pred_addr_or_pred_key, pred_ptr, addr_key, key, payload_ptr, retdest
%stack (pred_addr_or_pred_key, pred_ptr, addr_key, key, payload_ptr, retdest)
-> (retdest, payload_ptr)
// stack: pred_addr_or_pred_key, pred_ptr, addr_key, key, value, retdest
%stack (pred_addr_or_pred_key, pred_ptr, addr_key, key, value, retdest)
-> (retdest, value)
JUMP

slot_found_no_write:
// The slot was already in the list
// stack: pred_ptr, addr_key, key, payload_ptr, retdest
// Load the the payload pointer and access counter
// stack: pred_ptr, addr_key, key, value, retdest
// Load the old value
%add_const(2)
MLOAD_GENERAL
// stack: orig_value, addr_key, key, payload_ptr, retdest
%stack (orig_value, addr_key, key, payload_ptr, retdest) -> (retdest, orig_value)
// stack: old_value, addr_key, key, value, retdest
%stack (old_value, addr_key, key, value, retdest) -> (retdest, old_value)
JUMP

%macro search_slot
// stack: state_key, storage_key, ptr
%stack (state_key, storage_key, ptr) -> (state_key, storage_key, ptr, %%after)
%jump(search_slot)
%%after:
// stack: ptr
// stack: value
%endmacro

%macro remove_slot
Expand Down Expand Up @@ -875,7 +864,7 @@ remove_all_slots_end:
%stack (addr_key, key) -> (addr_key, key, 0, %%after)
%jump(search_slot)
%%after:
// stack: slot_ptr
// stack: slot_value
%endmacro

%macro read_storage_linked_list_w_addr
Expand All @@ -886,7 +875,7 @@ remove_all_slots_end:
%stack (addr_key, key) -> (addr_key, key, 0, %%after)
%jump(search_slot)
%%after:
// stack: slot_ptr
// stack: slot_value
%endmacro

%macro first_account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,14 @@

global sload_current:
%read_storage_linked_list
// stack: value_ptr, retdest
DUP1 %jumpi(storage_key_exists)

// Storage key not found. Return default value_ptr = 0,
// which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0.
%stack (value_ptr, retdest) -> (retdest, 0)
// stack: value, retdest
SWAP1
JUMP

// Read a word from the current account's storage trie.
//
// Pre stack: kexit_info, slot
// Post stack: value

global sys_sload:
// stack: kexit_info, slot
SWAP1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,6 @@ after_read:

sload_with_addr:
%read_storage_linked_list_w_addr
// stack: value_ptr, retdest
DUP1 %jumpi(storage_key_exists)
// Storage key not found. Return default value_ptr = 0,
// which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0.
%stack (value, retdest) -> (retdest, 0)

JUMP

global storage_key_exists:
// stack: value, retdest
SWAP1
JUMP
Loading