From 54557208475b3280774735030b76dd2aeb670cac Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 6 Aug 2024 14:13:34 -0400 Subject: [PATCH] Cherry pick what's left of Linked lists for the state trie (#402) --- Cargo.lock | 130 +++++++ Cargo.toml | 2 + .../src/cpu/kernel/asm/core/access_lists.asm | 2 +- .../kernel/asm/journal/account_destroyed.asm | 4 +- .../cpu/kernel/asm/journal/nonce_change.asm | 1 - .../src/cpu/kernel/asm/main.asm | 9 +- .../src/cpu/kernel/asm/mpt/delete/delete.asm | 2 +- .../asm/mpt/hash/hash_trie_specific.asm | 1 - .../asm/mpt/linked_list/final_tries.asm | 4 +- .../asm/mpt/linked_list/initial_tries.asm | 29 +- .../asm/mpt/linked_list/linked_list.asm | 81 +++-- .../asm/transactions/common_decoding.asm | 4 - .../cpu/kernel/constants/global_metadata.rs | 16 +- .../src/cpu/kernel/tests/account_code.rs | 18 +- .../src/cpu/kernel/tests/mpt/linked_list.rs | 152 +++++--- evm_arithmetization/src/generation/mpt.rs | 16 +- evm_arithmetization/tests/two_to_one_block.rs | 196 +++-------- trace_decoder/src/decoding.rs | 62 +++- trace_decoder/src/processed_block_trace.rs | 22 +- trace_decoder/src/typed_mpt.rs | 8 +- .../data/witnesses/zero_jerigon/b28_dev.json | 325 ++++++++++++++++++ .../zero_jerigon/b28_dev_header.json | 32 ++ zero_bin/README.md | 16 +- zero_bin/common/Cargo.toml | 7 + zero_bin/{leader => common}/build.rs | 13 +- zero_bin/common/src/lib.rs | 1 + .../common/src/prover_state/persistence.rs | 8 +- zero_bin/common/src/version.rs | 10 + zero_bin/leader/Cargo.toml | 4 +- zero_bin/leader/src/main.rs | 28 +- zero_bin/rpc/Cargo.toml | 6 + zero_bin/rpc/src/main.rs | 13 +- zero_bin/verifier/Cargo.toml | 6 + zero_bin/verifier/src/main.rs | 13 + zero_bin/worker/Cargo.toml | 6 + zero_bin/worker/src/main.rs | 15 +- 36 files changed, 960 insertions(+), 302 deletions(-) create mode 100644 trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev.json create mode 100644 trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev_header.json rename zero_bin/{leader => common}/build.rs (56%) create mode 100644 zero_bin/common/src/version.rs diff --git a/Cargo.lock b/Cargo.lock index c000658fc..2f1f34520 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1581,6 +1581,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.70", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.70", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -1658,6 +1693,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core", + "syn 2.0.70", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -2224,6 +2290,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getset" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "gimli" version = "0.29.0" @@ -2457,6 +2535,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -2768,6 +2852,7 @@ dependencies = [ "toml", "tracing", "tracing-subscriber", + "vergen", "zero_bin_common", ] @@ -3086,6 +3171,15 @@ dependencies = [ "syn 2.0.70", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "nunny" version = "0.2.1" @@ -4029,6 +4123,7 @@ version = "0.1.0" dependencies = [ "alloy", "anyhow", + "cargo_metadata", "clap", "compat", "evm_arithmetization", @@ -4045,6 +4140,7 @@ dependencies = [ "trace_decoder", "tracing-subscriber", "url", + "vergen", "zero_bin_common", ] @@ -4794,7 +4890,9 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -5253,11 +5351,38 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vergen" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c32e7318e93a9ac53693b6caccfb05ff22e04a44c7cf8a279051f24c09da286f" +dependencies = [ + "anyhow", + "derive_builder", + "rustc_version 0.4.0", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e06bee42361e43b60f363bad49d63798d0f42fb1768091812270eca00c784720" +dependencies = [ + "anyhow", + "derive_builder", + "getset", + "rustversion", +] + [[package]] name = "verifier" version = "0.1.0" dependencies = [ "anyhow", + "cargo_metadata", "clap", "dotenvy", "proof_gen", @@ -5265,6 +5390,7 @@ dependencies = [ "serde_path_to_error", "tracing", "tracing-subscriber", + "vergen", "zero_bin_common", ] @@ -5615,6 +5741,7 @@ name = "worker" version = "0.1.0" dependencies = [ "anyhow", + "cargo_metadata", "clap", "dotenvy", "jemallocator", @@ -5622,6 +5749,7 @@ dependencies = [ "paladin-core", "tokio", "tracing-subscriber", + "vergen", "zero_bin_common", ] @@ -5669,6 +5797,7 @@ dependencies = [ "alloy", "anyhow", "async-stream", + "cargo_metadata", "clap", "evm_arithmetization", "futures", @@ -5680,6 +5809,7 @@ dependencies = [ "tokio", "trace_decoder", "tracing", + "vergen", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3cb466c05..8c5753f8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ axum = "0.7.5" bitflags = "2.5.0" bitvec = "1.0.1" bytes = "1.6.0" +cargo_metadata = "0.18.1" ciborium = "0.2.2" ciborium-io = "0.2.2" clap = { version = "4.5.7", features = ["derive", "env"] } @@ -105,6 +106,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] } u4 = "0.1.0" uint = "0.9.5" url = "2.5.2" +vergen = { version = "9.0.0", features = ["build", "rustc"] } winnow = "0.6.13" # local dependencies diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/access_lists.asm b/evm_arithmetization/src/cpu/kernel/asm/core/access_lists.asm index d54d63a39..8a487fed0 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/access_lists.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/access_lists.asm @@ -386,4 +386,4 @@ global remove_accessed_storage_keys: // stack: next_next_ptr, next_ptr_ptr, addr, key, retdest MSTORE_GENERAL %pop2 - JUMP \ No newline at end of file + JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm index 45c178a6f..d62f3d422 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm @@ -30,9 +30,9 @@ revert_account_destroyed_contd: // stack: address, prev_balance, retdest %read_accounts_linked_list // stack: account_payload_ptr, prev_balance, retdest - DUP1 %assert_nonzero + DUP1 + %assert_nonzero %increment // stack: account_balance_payload_ptr, prev_balance, retdest %mstore_trie_data JUMP - diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm index 397957e0b..0c1198e52 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm @@ -16,4 +16,3 @@ global revert_nonce_change: %mstore_trie_data // stack: retdest JUMP - diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 3ec57ce22..bda72543b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -76,17 +76,12 @@ global main: // Encode constant nodes %initialize_rlp_segment - // Initialize linked list and trie data constants. - // TODO: Validate them. - PROVER_INPUT(linked_list::accounts_linked_list_len) - %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_LEN) - PROVER_INPUT(linked_list::storage_linked_list_len) - %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_LEN) + // Initialize trie data size. PROVER_INPUT(trie_ptr::trie_data_size) %mstore_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) global store_initial: - // Store the inital accounts and slots for hashing later + // Store the initial accounts and slots for hashing later %store_initial_accounts %store_initial_slots diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm index ffef18bbf..c878ae812 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm @@ -38,4 +38,4 @@ global delete_account: %jump(delete_account) %%after: // stack: (empty) -%endmacro \ No newline at end of file +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm index 923ca65ce..1da7c6a31 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm @@ -348,4 +348,3 @@ global encode_storage_value: // stack: rlp_addr', cur_len, retdest %stack (rlp_addr, cur_len, retdest) -> (retdest, rlp_addr, cur_len) JUMP - diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/final_tries.asm index 689dcb94a..9db07083d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/final_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/final_tries.asm @@ -90,7 +90,7 @@ after_insert_slot: %jump(insert_all_slots) // Delete all the accounts, referenced by the respective nodes in the linked list starting at -// `account_ptr_ptr`, which where deleted from the intial state. Delete also all slots of non-deleted accounts +// `account_ptr_ptr`, which where deleted from the initial state. Delete also all slots of non-deleted accounts // deleted from the storage trie. // Pre stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest // Post stack: new_root_ptr. @@ -100,7 +100,7 @@ global delete_removed_accounts: // We assume that the size of the initial accounts linked list, containing the accounts // of the initial state, was stored at `@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN`. %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) - // The inital accounts linked list was stored at addresses smaller than `@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN`. + // The initial accounts linked list was stored at addresses smaller than `@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN`. // If we also know that `@SEGMENT_ACCOUNT_LINKED_LIST <= account_ptr_ptr`, for deleting node at `addr_ptr_ptr` it // suffices to check that `account_ptr_ptr` != `@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN` EQ diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/initial_tries.asm index 9f3500fce..795453667 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/initial_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/initial_tries.asm @@ -2,7 +2,7 @@ // to mem[payload_ptr_ptr] + step*i, // for i =0..n_leaves. This is used to constraint the // initial state and account tries payload pointers such that they are exactly -// those of the inital accounts and linked lists. +// those of the initial accounts and linked lists. // Pre stack: node_ptr, account_ptr_ptr, storage_ptr_ptr, retdest // Post stack: account_ptr_ptr, storage_ptr_ptr global mpt_set_payload: @@ -17,6 +17,8 @@ global mpt_set_payload: DUP1 %eq_const(@MPT_NODE_BRANCH) %jumpi(set_payload_branch) DUP1 %eq_const(@MPT_NODE_EXTENSION) %jumpi(set_payload_extension) DUP1 %eq_const(@MPT_NODE_LEAF) %jumpi(set_payload_leaf) + DUP1 %eq_const(@MPT_NODE_HASH) %jumpi(skip) + PANIC skip: // stack: node_type, after_node_type, account_ptr_ptr, storage_ptr_ptr, retdest @@ -46,7 +48,7 @@ skip: %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) %endmacro -// Pre stack: node_ptr, account_ptr_ptr, retdest +// Pre stack: node_ptr, storage_ptr_ptr, retdest // Post stack: storage_ptr_ptr global mpt_set_storage_payload: // stack: node_ptr, storage_ptr_ptr, retdest @@ -116,18 +118,19 @@ set_payload_storage_branch: JUMP set_payload_extension: - // stack: node_type, after_node_type, storage_ptr_ptr, retdest + // stack: node_type, after_node_type, account_ptr_ptr, storage_ptr_ptr, retdest POP - // stack: after_node_type, storage_ptr_ptr, retdest + // stack: after_node_type, account_ptr_ptr, storage_ptr_ptr, retdest %add_const(2) %mload_trie_data - // stack: child_ptr, after_node_type, storage_ptr_ptr, retdest + // stack: child_ptr, after_node_type, account_ptr_ptr, storage_ptr_ptr, retdest %jump(mpt_set_payload) + set_payload_storage_extension: - // stack: node_type, after_node_type, account_ptr_ptr, storage_ptr_ptr, retdest + // stack: node_type, after_node_type, storage_ptr_ptr, retdest POP - // stack: after_node_type, account_ptr_ptr, storage_ptr_ptr, retdest + // stack: after_node_type, storage_ptr_ptr, retdest %add_const(2) %mload_trie_data - // stack: child_ptr, account_ptr_ptr, storage_ptr_ptr, retdest + // stack: child_ptr, storage_ptr_ptr, retdest %jump(mpt_set_storage_payload) set_payload_leaf: @@ -135,15 +138,13 @@ set_payload_leaf: POP %add_const(2) // The payload pointer starts at index 3, after num_nibbles and packed_nibbles. DUP1 - // stack payload_ptr_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr, retdest + // stack: payload_ptr_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr, retdest %mload_trie_data - // stack account_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr, retdest + // stack: account_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr, retdest %add_const(2) %mload_trie_data // storage_root_ptr = account[2] - DUP1 %mload_trie_data - POP - // stack storage_root_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr, retdest + // stack: storage_root_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr, retdest %stack (storage_root_ptr, payload_ptr_ptr, account_ptr_ptr, storage_ptr_ptr) -> (storage_root_ptr, storage_ptr_ptr, after_set_storage_payload, storage_root_ptr, payload_ptr_ptr, account_ptr_ptr) @@ -165,7 +166,7 @@ after_set_storage_payload: %mstore_trie_data // The dynamic account pointer in the linked list has no storage root so we need to manually set it. %mstore_trie_data // Set the leaf payload pointing to next account in the linked list. // stack: account_ptr_ptr, storage_ptr_ptr', retdest - %add_const(@STORAGE_NEXT_NODE_PTR) // The next pointer is at distance `STORAGE_NEXT_NODE_PTR` + %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) // The next pointer is at distance `ACCOUNTS_LINKED_LISTS_NODE_SIZE` // stack: payload_ptr_ptr', storage_ptr_ptr', retdest SWAP1 SWAP2 diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/linked_list.asm index 4e2862be5..d98abffed 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/linked_list.asm @@ -15,7 +15,7 @@ /// The values at the respective positions are: /// - 0: The account key /// - 1: A ptr to the payload (the account values) -/// - 2: A ptr to the intial payload. +/// - 2: A ptr to the initial payload. /// - 3: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. /// Similarly, an empty storage linked list is written as /// [@U256_MAX, _, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. @@ -34,51 +34,64 @@ %%after: %endmacro -/// Iterates over the inital account linked list and shallow copies +/// Iterates over the initial account linked list and shallow copies /// the accounts, storing a pointer to the copied account in the node. +/// Computes the length of `SEGMENT_ACCOUNTS_LINKED_LIST` and +/// stores it in `GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE`. global store_initial_accounts: // stack: retdest - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + ADD + // stack: cur_len, retdest + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST %next_account loop_store_initial_accounts: - // stack: current_node_ptr + // stack: current_node_ptr, cur_len, retdest %get_trie_data_size DUP2 MLOAD_GENERAL - // stack: current_addr_key, cpy_ptr, current_node_ptr, retdest + // stack: current_addr_key, cpy_ptr, current_node_ptr, cur_len, retdest %eq_const(@U256_MAX) %jumpi(store_initial_accounts_end) DUP2 %increment MLOAD_GENERAL - // stack: nonce_ptr, cpy_ptr, current_node_ptr, retdest + // stack: nonce_ptr, cpy_ptr, current_node_ptr, cur_len, retdest DUP1 %mload_trie_data // nonce %append_to_trie_data %increment - // stack: balance_ptr, cpy_ptr, current_node_ptr, retdest + // stack: balance_ptr, cpy_ptr, current_node_ptr, cur_len, retdest DUP1 %mload_trie_data // balance %append_to_trie_data %increment // The storage_root_ptr is not really necessary - // stack: storage_root_ptr_ptr, cpy_ptr, current_node_ptr, retdest + // stack: storage_root_ptr_ptr, cpy_ptr, current_node_ptr, cur_len, retdest DUP1 %mload_trie_data // storage_root_ptr %append_to_trie_data %increment - // stack: code_hash_ptr, cpy_ptr, current_node_ptr, retdest + // stack: code_hash_ptr, cpy_ptr, current_node_ptr, cur_len, retdest %mload_trie_data // code_hash %append_to_trie_data - // stack: cpy_ptr, current_node_ptr, retdest + // stack: cpy_ptr, current_node_ptr, cur_len, retdest DUP2 %add_const(2) SWAP1 MSTORE_GENERAL // Store cpy_ptr + // stack: current_node_ptr, cur_len, retdest + SWAP1 PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE + ADD + SWAP1 + // stack: current_node_ptr, cur_len', retdest %next_account %jump(loop_store_initial_accounts) store_initial_accounts_end: %pop2 + // stack: cur_len, retdest + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) JUMP %macro insert_account_with_overwrite @@ -88,7 +101,7 @@ store_initial_accounts_end: %endmacro // Multiplies the value at the top of the stack, denoted by ptr/4, by 4 -// and aborts if ptr/4 <= mem[@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_LEN]/4. +// and aborts if ptr/4 <= mem[@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE]/4. // Also checks that ptr >= @SEGMENT_ACCOUNTS_LINKED_LIST. // This way, 4*ptr/4 must be pointing to the beginning of a node. // TODO: Maybe we should check here if the node has been deleted. @@ -103,7 +116,7 @@ store_initial_accounts_end: // stack: ptr/4 DUP1 PUSH 4 - %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_LEN) + %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) // By construction, both @SEGMENT_ACCOUNTS_LINKED_LIST and the unscaled list len // must be multiples of 4 DIV @@ -159,7 +172,7 @@ insert_new_account: // get the value of the next address %add_const(@ACCOUNTS_NEXT_NODE_PTR) // stack: next_ptr_ptr, addr_key, payload_ptr, retdest - %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_LEN) + %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) DUP2 MLOAD_GENERAL // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest @@ -201,14 +214,14 @@ insert_new_account: MSTORE_GENERAL // stack: new_next_ptr, addr_key, payload_ptr, retdest %increment - %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_LEN) + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) // stack: addr_key, payload_ptr, retdest %pop2 JUMP /// Searches the account addr in the linked list. -/// Returns `payload_ptr` if the account was not found, `original_ptr` if it was already present. +/// Returns 0 if the account was not found or `original_ptr` if it was already present. global search_account: // stack: addr_key, retdest PROVER_INPUT(linked_list::insert_account) @@ -307,11 +320,17 @@ global remove_account: %endmacro -/// Iterates over the inital account linked list and shallow copies +/// Iterates over the initial account linked list and shallow copies /// the accounts, storing a pointer to the copied account in the node. +/// Computes the length of `SEGMENT_STORAGE_LINKED_LIST` and +/// checks against `GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE`. global store_initial_slots: // stack: retdest - PUSH @SEGMENT_STORAGE_LINKED_LIST + PUSH @STORAGE_LINKED_LISTS_NODE_SIZE + PUSH @SEGMENT_STORAGE_LINKED_LIST + ADD + // stack: cur_len, retdest + PUSH @SEGMENT_STORAGE_LINKED_LIST %next_slot loop_store_initial_slots: @@ -357,7 +376,7 @@ store_initial_slots_end: %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_LEN] - @SEGMENT_STORAGE_LINKED_LIST)/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. // TODO: Maybe we should check here if the node has been deleted. %macro get_valid_slot_ptr @@ -366,7 +385,7 @@ store_initial_slots_end: PUSH 5 PUSH @SEGMENT_STORAGE_LINKED_LIST // stack: segment, 5, ptr/5, ptr/5 - %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_LEN) + %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) SUB // stack: accessed_strg_keys_len, 5, ptr/5, ptr/5 // By construction, the unscaled list len must be multiple of 5 @@ -430,7 +449,7 @@ insert_new_slot_with_value: // get the value of the next address %add_const(@STORAGE_NEXT_NODE_PTR) // stack: next_ptr_ptr, addr_key, key, value, retdest - %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_LEN) + %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) DUP2 MLOAD_GENERAL // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest @@ -518,6 +537,7 @@ slot_found_write_value: %stack (slot_key, addr_key, value) -> (addr_key, slot_key, value, %%after) %jump(insert_slot_with_value) %%after: + // stack: (empty) %endmacro %macro insert_slot_with_value_from_keys @@ -525,8 +545,6 @@ slot_found_write_value: %stack (addr_key, slot_key, value) -> (addr_key, slot_key, value, %%after) %jump(insert_slot_with_value) %%after: - // stack: value_ptr - POP // stack: (empty) %endmacro @@ -598,7 +616,7 @@ insert_new_slot: // get the value of the next address %add_const(@STORAGE_NEXT_NODE_PTR) // stack: next_ptr_ptr, addr_key, key, payload_ptr, retdest - %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_LEN) + %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 @@ -669,7 +687,7 @@ next_node_ok: MSTORE_GENERAL // stack: new_next_ptr, addr_key, key, payload_ptr, retdest %increment - %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_LEN) + %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) JUMP @@ -737,6 +755,13 @@ slot_found_no_write: %stack (orig_value, addr_key, key, payload_ptr, retdest) -> (retdest, orig_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 +%endmacro %macro remove_slot %stack (key, addr_key) -> (addr_key, key, %%after) @@ -864,14 +889,6 @@ remove_all_slots_end: // stack: slot_ptr %endmacro -%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 -%endmacro - %macro first_account // stack: empty PUSH @SEGMENT_ACCOUNTS_LINKED_LIST diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm index b9691d9e0..5109f29af 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm @@ -305,14 +305,10 @@ after_read: POP JUMP - 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) diff --git a/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs b/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs index 9a07884eb..c81d4f4b2 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs @@ -104,10 +104,10 @@ pub(crate) enum GlobalMetadata { /// The address of the next available address in /// Segment::AccountsLinkedList - AccountsLinkedListLen, + AccountsLinkedListNextAvailable, /// The address of the next available address in /// Segment::StorageLinkedList - StorageLinkedListLen, + StorageLinkedListNextAvailable, /// Length of the `AccountsLinkedList` segment after insertion of the /// initial accounts. InitialAccountsLinkedListLen, @@ -187,8 +187,8 @@ impl GlobalMetadata { Self::CreatedContractsLen, Self::KernelHash, Self::KernelLen, - Self::AccountsLinkedListLen, - Self::StorageLinkedListLen, + Self::AccountsLinkedListNextAvailable, + Self::StorageLinkedListNextAvailable, Self::InitialAccountsLinkedListLen, Self::InitialStorageLinkedListLen, Self::TransientStorageLen, @@ -252,8 +252,12 @@ impl GlobalMetadata { Self::CreatedContractsLen => "GLOBAL_METADATA_CREATED_CONTRACTS_LEN", Self::KernelHash => "GLOBAL_METADATA_KERNEL_HASH", Self::KernelLen => "GLOBAL_METADATA_KERNEL_LEN", - Self::AccountsLinkedListLen => "GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_LEN", - Self::StorageLinkedListLen => "GLOBAL_METADATA_STORAGE_LINKED_LIST_LEN", + Self::AccountsLinkedListNextAvailable => { + "GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE" + } + Self::StorageLinkedListNextAvailable => { + "GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE" + } Self::InitialAccountsLinkedListLen => { "GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN" } diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index b9a62f207..3656f26c3 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -68,12 +68,12 @@ pub(crate) fn initialize_mpts( let accounts_len_addr = MemoryAddress { context: 0, segment: Segment::GlobalMetadata.unscale(), - virt: GlobalMetadata::AccountsLinkedListLen.unscale(), + virt: GlobalMetadata::AccountsLinkedListNextAvailable.unscale(), }; let storage_len_addr = MemoryAddress { context: 0, segment: Segment::GlobalMetadata.unscale(), - virt: GlobalMetadata::StorageLinkedListLen.unscale(), + virt: GlobalMetadata::StorageLinkedListNextAvailable.unscale(), }; let initial_accounts_len_addr = MemoryAddress { context: 0, @@ -201,7 +201,7 @@ pub(crate) fn prepare_interpreter( .expect("The stack should not overflow"); interpreter .push(interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot)) - .unwrap(); + .expect("The stack should not overflow"); // Now, set the payload. interpreter.generation_state.registers.program_counter = @@ -215,7 +215,7 @@ pub(crate) fn prepare_interpreter( interpreter.set_global_metadata_field(GlobalMetadata::InitialStorageLinkedListLen, storage_ptr); // Now, execute `mpt_hash_state_trie`. - state_trie.insert(k, rlp::encode(account).to_vec()).unwrap(); + state_trie.insert(k, rlp::encode(account).to_vec())?; let expected_state_trie_hash = state_trie.hash(); interpreter.set_global_metadata_field( GlobalMetadata::StateTrieRootDigestAfter, @@ -403,7 +403,7 @@ fn prepare_interpreter_all_accounts( KERNEL.global_labels["store_initial_slots"]; interpreter.run()?; - // Set the pointers to the intial payloads. + // Set the pointers to the initial payloads. interpreter .push(0xDEADBEEFu32.into()) .expect("The stack should not overflow"); @@ -415,7 +415,7 @@ fn prepare_interpreter_all_accounts( .expect("The stack should not overflow"); interpreter .push(interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot)) - .unwrap(); + .expect("The stack should not overflow"); // Now, set the payloads in the state trie leaves. interpreter.generation_state.registers.program_counter = @@ -426,7 +426,7 @@ fn prepare_interpreter_all_accounts( assert_eq!( interpreter.stack().len(), 2, - "Expected 2 items on stack after setting the inital trie payloads, found {:?}", + "Expected 2 items on stack after setting the initial trie payloads, found {:?}", interpreter.stack() ); @@ -525,9 +525,7 @@ fn sstore() -> Result<()> { }; let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after - .insert(addr_nibbles, rlp::encode(&account_after).to_vec()) - .unwrap(); + expected_state_trie_after.insert(addr_nibbles, rlp::encode(&account_after).to_vec())?; let expected_state_trie_hash = expected_state_trie_after.hash(); diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs index bff03cf1d..69f7061bc 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs @@ -45,7 +45,7 @@ fn test_init_linked_lists() -> Result<()> { acc_addr_list ); - // Check the inital storage linked list + // Check the initial storage linked list let acc_addr_list: Vec = (0..5) .map(|i| { interpreter @@ -140,7 +140,7 @@ fn test_insert_account() -> Result<()> { [Segment::AccountsLinkedList.unscale()] .content = init_accounts_ll; interpreter.set_global_metadata_field( - GlobalMetadata::AccountsLinkedListLen, + GlobalMetadata::AccountsLinkedListNextAvailable, (Segment::AccountsLinkedList as usize + init_len).into(), ); @@ -153,9 +153,15 @@ fn test_insert_account() -> Result<()> { assert!(address != H160::zero(), "Cosmic luck or bad RNG?"); - interpreter.push(retaddr).unwrap(); - interpreter.push(payload_ptr).unwrap(); - interpreter.push(U256::from(address.0.as_slice())).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); + interpreter + .push(payload_ptr) + .expect("The stack should not overflow"); + interpreter + .push(U256::from(address.0.as_slice())) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_account_label; interpreter.run()?; @@ -209,7 +215,7 @@ fn test_insert_storage() -> Result<()> { [Segment::StorageLinkedList.unscale()] .content = init_storage_ll; interpreter.set_global_metadata_field( - GlobalMetadata::StorageLinkedListLen, + GlobalMetadata::StorageLinkedListNextAvailable, (Segment::StorageLinkedList as usize + init_len).into(), ); @@ -223,10 +229,18 @@ fn test_insert_storage() -> Result<()> { assert!(address != H160::zero(), "Cosmic luck or bad RNG?"); - interpreter.push(retaddr).unwrap(); - interpreter.push(payload_ptr).unwrap(); - interpreter.push(U256::from(key.0.as_slice())).unwrap(); - interpreter.push(U256::from(address.0.as_slice())).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); + interpreter + .push(payload_ptr) + .expect("The stack should not overflow"); + interpreter + .push(U256::from(key.0.as_slice())) + .expect("The stack should not overflow"); + interpreter + .push(U256::from(address.0.as_slice())) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_account_label; interpreter.run()?; @@ -282,7 +296,7 @@ fn test_insert_and_delete_accounts() -> Result<()> { [Segment::AccountsLinkedList.unscale()] .content = init_accounts_ll; interpreter.set_global_metadata_field( - GlobalMetadata::AccountsLinkedListLen, + GlobalMetadata::AccountsLinkedListNextAvailable, (Segment::AccountsLinkedList as usize + init_len).into(), ); @@ -306,9 +320,15 @@ fn test_insert_and_delete_accounts() -> Result<()> { // Insert all addresses for i in 0..n { let addr = U256::from(addresses[i].0.as_slice()); - interpreter.push(0xdeadbeefu32.into()).unwrap(); - interpreter.push(addr + delta_ptr).unwrap(); // ptr = addr + delta_ptr for the sake of the test - interpreter.push(addr).unwrap(); + interpreter + .push(0xdeadbeefu32.into()) + .expect("The stack should not overflow"); + interpreter + .push(addr + delta_ptr) + .expect("The stack should not overflow"); // ptr = addr + delta_ptr for the sake of the test + interpreter + .push(addr) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_account_label; interpreter.run()?; @@ -326,8 +346,10 @@ fn test_insert_and_delete_accounts() -> Result<()> { // 1)*4. assert_eq!( interpreter.generation_state.memory.get_with_init( - MemoryAddress::new_bundle(U256::from(GlobalMetadata::AccountsLinkedListLen as usize)) - .unwrap(), + MemoryAddress::new_bundle(U256::from( + GlobalMetadata::AccountsLinkedListNextAvailable as usize + )) + .unwrap(), ), U256::from(offset + (n + 1) * 4) ); @@ -336,8 +358,12 @@ fn test_insert_and_delete_accounts() -> Result<()> { // Test for address already in list. for i in 0..n { let addr_in_list = U256::from(addresses[i].0.as_slice()); - interpreter.push(retaddr).unwrap(); - interpreter.push(addr_in_list).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); + interpreter + .push(addr_in_list) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = search_account_label; interpreter.run()?; @@ -348,13 +374,15 @@ fn test_insert_and_delete_accounts() -> Result<()> { } // Test for address not in the list. - interpreter.push(retaddr).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); interpreter .push(U256::from(addr_not_in_list.0.as_slice()) + delta_ptr) - .unwrap(); + .expect("The stack should not overflow"); interpreter .push(U256::from(addr_not_in_list.0.as_slice())) - .unwrap(); + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_account_label; interpreter.run()?; @@ -366,8 +394,10 @@ fn test_insert_and_delete_accounts() -> Result<()> { // 2)*4. assert_eq!( interpreter.generation_state.memory.get_with_init( - MemoryAddress::new_bundle(U256::from(GlobalMetadata::AccountsLinkedListLen as usize)) - .unwrap(), + MemoryAddress::new_bundle(U256::from( + GlobalMetadata::AccountsLinkedListNextAvailable as usize + )) + .unwrap(), ), U256::from(offset + (n + 2) * 4) ); @@ -380,8 +410,12 @@ fn test_insert_and_delete_accounts() -> Result<()> { for (i, j) in (0..n).tuples() { // Remove addressese already in list. let addr_in_list = U256::from(addresses[i].0.as_slice()); - interpreter.push(retaddr).unwrap(); - interpreter.push(addr_in_list).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); + interpreter + .push(addr_in_list) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = delete_account_label; interpreter.run()?; assert!(interpreter.stack().is_empty()); @@ -436,7 +470,7 @@ fn test_insert_and_delete_storage() -> Result<()> { [Segment::StorageLinkedList.unscale()] .content = init_storage_ll; interpreter.set_global_metadata_field( - GlobalMetadata::StorageLinkedListLen, + GlobalMetadata::StorageLinkedListNextAvailable, (Segment::StorageLinkedList as usize + init_len).into(), ); @@ -466,10 +500,18 @@ fn test_insert_and_delete_storage() -> Result<()> { // Insert all addresses, key pairs for i in 0..n { let [addr, key] = addresses_and_keys[i].map(|x| U256::from(x.0.as_slice())); - interpreter.push(0xdeadbeefu32.into()).unwrap(); - interpreter.push(addr + delta_ptr).unwrap(); // ptr = addr + delta_ptr for the sake of the test - interpreter.push(key).unwrap(); - interpreter.push(addr).unwrap(); + interpreter + .push(0xdeadbeefu32.into()) + .expect("The stack should not overflow"); + interpreter + .push(addr + delta_ptr) + .expect("The stack should not overflow"); // ptr = addr + delta_ptr for the sake of the test + interpreter + .push(key) + .expect("The stack should not overflow"); + interpreter + .push(addr) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_slot_label; interpreter.run()?; assert_eq!( @@ -489,8 +531,10 @@ fn test_insert_and_delete_storage() -> Result<()> { // 1)*5. assert_eq!( interpreter.generation_state.memory.get_with_init( - MemoryAddress::new_bundle(U256::from(GlobalMetadata::StorageLinkedListLen as usize)) - .unwrap(), + MemoryAddress::new_bundle(U256::from( + GlobalMetadata::StorageLinkedListNextAvailable as usize + )) + .unwrap(), ), U256::from(offset + (n + 1) * 5) ); @@ -498,10 +542,18 @@ fn test_insert_and_delete_storage() -> Result<()> { // Test for address already in list. for i in 0..n { let [addr_in_list, key_in_list] = addresses_and_keys[i].map(|x| U256::from(x.0.as_slice())); - interpreter.push(retaddr).unwrap(); - interpreter.push(addr_in_list + delta_ptr).unwrap(); - interpreter.push(key_in_list).unwrap(); - interpreter.push(addr_in_list).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); + interpreter + .push(addr_in_list + delta_ptr) + .expect("The stack should not overflow"); + interpreter + .push(key_in_list) + .expect("The stack should not overflow"); + interpreter + .push(addr_in_list) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_slot_label; interpreter.run()?; @@ -518,16 +570,18 @@ fn test_insert_and_delete_storage() -> Result<()> { } // Test for address not in the list. - interpreter.push(retaddr).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); interpreter .push(U256::from(addr_not_in_list.0.as_slice()) + delta_ptr) - .unwrap(); + .expect("The stack should not overflow"); interpreter .push(U256::from(key_not_in_list.0.as_slice())) - .unwrap(); + .expect("The stack should not overflow"); interpreter .push(U256::from(addr_not_in_list.0.as_slice())) - .unwrap(); + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_slot_label; interpreter.run()?; @@ -544,8 +598,10 @@ fn test_insert_and_delete_storage() -> Result<()> { // 2)*5. assert_eq!( interpreter.generation_state.memory.get_with_init( - MemoryAddress::new_bundle(U256::from(GlobalMetadata::StorageLinkedListLen as usize)) - .unwrap(), + MemoryAddress::new_bundle(U256::from( + GlobalMetadata::StorageLinkedListNextAvailable as usize + )) + .unwrap(), ), U256::from(offset + (n + 2) * 5) ); @@ -558,9 +614,15 @@ fn test_insert_and_delete_storage() -> Result<()> { for (i, j) in (0..n).tuples() { // Test for [address, key] already in list. let [addr_in_list, key_in_list] = addresses_and_keys[i].map(|x| U256::from(x.0.as_slice())); - interpreter.push(retaddr).unwrap(); - interpreter.push(key_in_list).unwrap(); - interpreter.push(addr_in_list).unwrap(); + interpreter + .push(retaddr) + .expect("The stack should not overflow"); + interpreter + .push(key_in_list) + .expect("The stack should not overflow"); + interpreter + .push(addr_in_list) + .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = remove_slot_label; interpreter.run()?; assert!(interpreter.stack().is_empty()); diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 65abe994b..1af32a05b 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -72,7 +72,12 @@ impl LegacyReceiptRlp { } } -pub(crate) fn parse_receipts(rlp: &[u8]) -> Result, ProgramError> { +/// Decodes a transaction receipt from an RLP string, outputting a tuple +/// consisting of: +/// - the receipt's [`PayloadInfo`], +/// - the transaction type, +/// - the decoded [`LegacyReceiptRlp`]. +pub fn decode_receipt(rlp: &[u8]) -> Result<(PayloadInfo, usize, LegacyReceiptRlp), ProgramError> { let txn_type = match rlp.first().ok_or(ProgramError::InvalidRlp)? { 1 => 1, 2 => 2, @@ -87,6 +92,11 @@ pub(crate) fn parse_receipts(rlp: &[u8]) -> Result, ProgramError> { let decoded_receipt: LegacyReceiptRlp = rlp::decode(rlp).map_err(|_| ProgramError::InvalidRlp)?; + Ok((payload_info, txn_type, decoded_receipt)) +} + +pub(crate) fn parse_receipts(rlp: &[u8]) -> Result, ProgramError> { + let (payload_info, txn_type, decoded_receipt) = decode_receipt(rlp)?; let mut parsed_receipt = if txn_type == 0 { Vec::new() } else { @@ -396,7 +406,7 @@ fn get_state_and_storage_leaves( state_leaves.push(Some(trie_data.len().into())); // Set counter. state_leaves.push(Some(0.into())); - // Set the next node as the inital node. + // Set the next node as the initial node. state_leaves.push(Some((Segment::AccountsLinkedList as usize).into())); // Push the payload in the trie data. @@ -476,7 +486,7 @@ where storage_leaves.push(leaf); // Write the counter. storage_leaves.push(Some(0.into())); - // Set the next node as the inital node. + // Set the next node as the initial node. storage_leaves.push(Some((Segment::StorageLinkedList as usize).into())); Ok(()) diff --git a/evm_arithmetization/tests/two_to_one_block.rs b/evm_arithmetization/tests/two_to_one_block.rs index 21f8ac6b5..59f0c377d 100644 --- a/evm_arithmetization/tests/two_to_one_block.rs +++ b/evm_arithmetization/tests/two_to_one_block.rs @@ -1,18 +1,17 @@ -use std::collections::HashMap; -use std::str::FromStr; - use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; -use ethereum_types::{Address, BigEndianHash, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::fixed_recursive_verifier::{ extract_block_public_values, extract_two_to_one_block_hash, }; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockMetadata, PublicValues, TrieRoots}; +use evm_arithmetization::testing_utils::{ + beacon_roots_account_nibbles, beacon_roots_contract_from_storage, ger_account_nibbles, + preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, + GLOBAL_EXIT_ROOT_ACCOUNT, +}; use evm_arithmetization::{AllRecursiveCircuits, AllStark, Node, StarkConfig}; use hex_literal::hex; -use keccak_hash::keccak; -use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::hash::poseidon::PoseidonHash; @@ -24,59 +23,14 @@ type F = GoldilocksField; const D: usize = 2; type C = PoseidonGoldilocksConfig; -fn eth_to_wei(eth: U256) -> U256 { - // 1 ether = 10^18 wei. - eth * U256::from(10).pow(18.into()) -} - fn init_logger() { let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); } -/// Get `GenerationInputs` for a simple token transfer txn, where the block has -/// the given timestamp. -fn empty_transfer(timestamp: u64) -> anyhow::Result { - init_logger(); - +/// Get `GenerationInputs` for a dummy payload, where the block has the given +/// timestamp. +fn dummy_payload(timestamp: u64, is_first_payload: bool) -> anyhow::Result { let beneficiary = hex!("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); - let sender = hex!("2c7536e3605d9c16a7a3d7b1898e529396a65c23"); - let to = hex!("a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0"); - - let sender_state_key = keccak(sender); - let to_state_key = keccak(to); - - 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 sender_account_before = AccountRlp { - nonce: 5.into(), - balance: eth_to_wei(100_000.into()), - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: keccak([]), - }; - let to_account_before = AccountRlp::default(); - - let state_trie_before: HashedPartialTrie = Node::Leaf { - nibbles: sender_nibbles, - value: rlp::encode(&sender_account_before).to_vec(), - } - .into(); - let checkpoint_state_trie_root = state_trie_before.hash(); - assert_eq!( - checkpoint_state_trie_root, - hex!("ef46022eafbc33d70e6ea9c6aef1074c1ff7ad36417ffbc64307ad3a8c274b75").into() - ); - - let tries_before = TrieInputs { - state_trie: HashedPartialTrie::from(Node::Empty), - transactions_trie: HashedPartialTrie::from(Node::Empty), - receipts_trie: HashedPartialTrie::from(Node::Empty), - storage_tries: vec![], - }; - - // Generated using a little py-evm script. - let txn = hex!("f861050a8255f094a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0648242421ba02c89eb757d9deeb1f5b3859a9d4d679951ef610ac47ad4608dc142beb1b7e313a05af7e9fbab825455d36c36c7f4cfcafbeafa9a77bdff936b52afb36d4fe4bcdd"); - let value = U256::from(100u32); let block_metadata = BlockMetadata { block_beneficiary: Address::from(beneficiary), @@ -90,73 +44,58 @@ fn empty_transfer(timestamp: u64) -> anyhow::Result { ..Default::default() }; - let contract_code = HashMap::new(); - - let expected_state_trie_after: HashedPartialTrie = { - let txdata_gas = 2 * 16; - let gas_used = 21_000 + txdata_gas; - - let sender_account_after = AccountRlp { - balance: sender_account_before.balance - value - gas_used * 10, - nonce: sender_account_before.nonce + 1, - ..sender_account_before - }; - let to_account_after = AccountRlp { - balance: value, - ..to_account_before - }; - - let mut children = core::array::from_fn(|_| Node::Empty.into()); - children[sender_nibbles.get_nibble(0) as usize] = Node::Leaf { - nibbles: sender_nibbles.truncate_n_nibbles_front(1), - value: rlp::encode(&sender_account_after).to_vec(), - } - .into(); - children[to_nibbles.get_nibble(0) as usize] = Node::Leaf { - nibbles: to_nibbles.truncate_n_nibbles_front(1), - value: rlp::encode(&to_account_after).to_vec(), - } - .into(); - Node::Branch { - children, - value: vec![], - } - .into() - }; + let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; + let checkpoint_state_trie_root = state_trie_before.hash(); + let mut beacon_roots_account_storage = storage_tries[0].1.clone(); - let receipt_0 = LegacyReceiptRlp { - status: true, - cum_gas_used: 21032.into(), - bloom: vec![0; 256].into(), - logs: vec![], - }; - let mut receipts_trie = HashedPartialTrie::from(Node::Empty); - receipts_trie.insert( - Nibbles::from_str("0x80").unwrap(), - rlp::encode(&receipt_0).to_vec(), + update_beacon_roots_account_storage( + &mut beacon_roots_account_storage, + block_metadata.block_timestamp, + block_metadata.parent_beacon_block_root, )?; - let transactions_trie: HashedPartialTrie = Node::Leaf { - nibbles: Nibbles::from_str("0x80").unwrap(), - value: txn.to_vec(), + let updated_beacon_roots_account = + beacon_roots_contract_from_storage(&beacon_roots_account_storage); + + if !is_first_payload { + // This isn't the first dummy payload being processed. We need to update the + // initial state trie to account for the update on the beacon roots contract. + state_trie_before.insert( + beacon_roots_account_nibbles(), + rlp::encode(&updated_beacon_roots_account).to_vec(), + )?; + storage_tries[0].1 = beacon_roots_account_storage; } - .into(); - let _trie_roots_after = TrieRoots { - state_root: expected_state_trie_after.hash(), - transactions_root: transactions_trie.hash(), - receipts_root: receipts_trie.hash(), + let tries_before = TrieInputs { + state_trie: state_trie_before, + storage_tries, + ..Default::default() + }; + + let expected_state_trie_after: HashedPartialTrie = { + let mut state_trie_after = HashedPartialTrie::from(Node::Empty); + state_trie_after.insert( + beacon_roots_account_nibbles(), + rlp::encode(&updated_beacon_roots_account).to_vec(), + )?; + state_trie_after.insert( + ger_account_nibbles(), + rlp::encode(&GLOBAL_EXIT_ROOT_ACCOUNT).to_vec(), + )?; + + state_trie_after }; let trie_roots_after = TrieRoots { - state_root: tries_before.state_trie.hash(), + state_root: expected_state_trie_after.hash(), transactions_root: tries_before.transactions_trie.hash(), receipts_root: tries_before.receipts_trie.hash(), }; + let inputs = GenerationInputs { tries: tries_before.clone(), trie_roots_after, - contract_code, - checkpoint_state_trie_root: tries_before.state_trie.hash(), + checkpoint_state_trie_root, block_metadata, ..Default::default() }; @@ -170,46 +109,23 @@ fn get_test_block_proof( all_stark: &AllStark, config: &StarkConfig, ) -> anyhow::Result> { - let inputs0 = empty_transfer(timestamp)?; - let inputs = inputs0.clone(); - let dummy0 = GenerationInputs { - txn_number_before: inputs.txn_number_before, - gas_used_before: inputs.gas_used_after, - gas_used_after: inputs.gas_used_after, - signed_txns: vec![], - global_exit_roots: vec![], - withdrawals: vec![], - tries: TrieInputs { - state_trie: HashedPartialTrie::from(Node::Hash(inputs.trie_roots_after.state_root)), - transactions_trie: HashedPartialTrie::from(Node::Hash( - inputs.trie_roots_after.transactions_root, - )), - receipts_trie: HashedPartialTrie::from(Node::Hash( - inputs.trie_roots_after.receipts_root, - )), - storage_tries: vec![], - }, - trie_roots_after: inputs.trie_roots_after, - checkpoint_state_trie_root: inputs.checkpoint_state_trie_root, - contract_code: Default::default(), - block_metadata: inputs.block_metadata.clone(), - block_hashes: inputs.block_hashes.clone(), - }; + let dummy0 = dummy_payload(timestamp, true)?; + let dummy1 = dummy_payload(timestamp, false)?; let timing = &mut TimingTree::new(&format!("Blockproof {timestamp}"), log::Level::Info); - let inputs0_segment_proofs = - all_circuits.prove_all_segments(all_stark, config, inputs0, 20, timing, None)?; - let dummy0_proof = + let dummy0_proof0 = all_circuits.prove_all_segments(all_stark, config, dummy0, 20, timing, None)?; + let dummy1_proof = + all_circuits.prove_all_segments(all_stark, config, dummy1, 20, timing, None)?; let inputs0_proof = all_circuits.prove_segment_aggregation( false, - &inputs0_segment_proofs[0], + &dummy0_proof0[0], false, - &inputs0_segment_proofs[1], + &dummy0_proof0[1], )?; let dummy0_proof = - all_circuits.prove_segment_aggregation(false, &dummy0_proof[0], false, &dummy0_proof[1])?; + all_circuits.prove_segment_aggregation(false, &dummy1_proof[0], false, &dummy1_proof[1])?; let (agg_proof0, pv0) = all_circuits.prove_transaction_aggregation( false, diff --git a/trace_decoder/src/decoding.rs b/trace_decoder/src/decoding.rs index b1f9bfd89..0414679b6 100644 --- a/trace_decoder/src/decoding.rs +++ b/trace_decoder/src/decoding.rs @@ -7,7 +7,10 @@ use std::{ use ethereum_types::{Address, BigEndianHash, H256, U256, U512}; use evm_arithmetization::{ - generation::{mpt::AccountRlp, GenerationInputs, TrieInputs}, + generation::{ + mpt::{decode_receipt, AccountRlp}, + GenerationInputs, TrieInputs, + }, proof::{BlockMetadata, ExtraBlockData, TrieRoots}, testing_utils::{BEACON_ROOTS_CONTRACT_ADDRESS_HASHED, HISTORY_BUFFER_LENGTH}, }; @@ -153,6 +156,10 @@ pub enum TraceParsingErrorReason { #[error("Failed to decode RLP bytes ({0}) as an Ethereum account due to the error: {1}")] AccountDecode(String, String), + /// Failure to decode a transaction receipt. + #[error("Failed to decode RLP bytes ({0}) as a transaction receipt due to the error: {1}")] + ReceiptDecode(String, String), + /// Failure due to trying to access or delete a storage trie missing /// from the base trie. #[error("Missing account storage trie in base trie when constructing subset partial trie for txn (account: {0:x})")] @@ -471,6 +478,7 @@ impl ProcessedBlockTrace { fn apply_deltas_to_trie_state( trie_state: &mut PartialTrieState, deltas: &NodesUsedByTxn, + meta: &[TxnMetaState], ) -> TraceParsingResult { let mut out = TrieDeltaApplicationOutput::default(); @@ -518,11 +526,11 @@ impl ProcessedBlockTrace { for (hashed_acc_addr, s_trie_writes) in deltas.state_writes.iter() { let val_k = Nibbles::from_h256_be(*hashed_acc_addr); - // If the account was created, then it will not exist in the trie. - let val_bytes = trie_state - .state - .get(val_k) - .unwrap_or(&EMPTY_ACCOUNT_BYTES_RLPED); + // If the account was created, then it will not exist yet in the trie. + let (is_created, val_bytes) = match trie_state.state.get(val_k) { + Some(bytes) => (false, bytes), + None => (true, &EMPTY_ACCOUNT_BYTES_RLPED[..]), + }; let mut account = account_from_rlped_bytes(val_bytes)?; @@ -533,6 +541,41 @@ impl ProcessedBlockTrace { )?; let updated_account_bytes = rlp::encode(&account); + if is_created { + // If the account did not exist prior this transaction, we + // need to make sure the transaction didn't revert. + + // We will check the status of the last receipt that attempted to create the + // account in this batch. + let last_creation_receipt = &meta + .iter() + .rev() + .find(|tx| tx.created_accounts.contains(hashed_acc_addr)) + .expect("We should have found a matching transaction") + .receipt_node_bytes; + + let (_, _, receipt) = decode_receipt(&last_creation_receipt).map_err(|err| { + Box::new(TraceParsingError::new( + TraceParsingErrorReason::ReceiptDecode( + hex::encode(&last_creation_receipt), + format!("{:?}", err), + ), + )) + })?; + + if !receipt.status { + // The transaction failed, hence any created account should be removed. + trie_state + .state + .delete(val_k) + .map_err(TraceParsingError::from)?; + + trie_state.storage.remove(hashed_acc_addr); + + continue; + } + } + trie_state .state .insert(val_k, updated_account_bytes.to_vec()) @@ -712,8 +755,11 @@ impl ProcessedBlockTrace { .map_err(TraceParsingError::from)?; } - let mut delta_out = - Self::apply_deltas_to_trie_state(curr_block_tries, &txn_info.nodes_used_by_txn)?; + let mut delta_out = Self::apply_deltas_to_trie_state( + curr_block_tries, + &txn_info.nodes_used_by_txn, + &txn_info.meta, + )?; let nodes_used_by_txn = if is_initial_payload { let mut nodes_used = txn_info.nodes_used_by_txn; diff --git a/trace_decoder/src/processed_block_trace.rs b/trace_decoder/src/processed_block_trace.rs index 42e8eb34a..2380b6425 100644 --- a/trace_decoder/src/processed_block_trace.rs +++ b/trace_decoder/src/processed_block_trace.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt::Debug; use std::iter::once; @@ -78,7 +78,12 @@ impl TxnInfo { let mut contract_code_accessed = create_empty_code_access_map(); let mut meta = Vec::with_capacity(tx_infos.len()); + let all_accounts: BTreeSet = + all_accounts_in_pre_image.iter().map(|(h, _)| *h).collect(); + for txn in tx_infos.iter() { + let mut created_accounts = BTreeSet::new(); + for (addr, trace) in txn.traces.iter() { let hashed_addr = hash(addr.as_bytes()); @@ -96,14 +101,14 @@ impl TxnInfo { if let Some(storage) = nodes_used_by_txn.storage_accesses.get_mut(&hashed_addr) { storage.extend( &storage_access_keys - .map(|k| Nibbles::from_h256_be(hash(&k.0))) + .map(|k| Nibbles::from_h256_be(hash(k.0))) .collect::>(), ) } else { nodes_used_by_txn.storage_accesses.insert( hashed_addr, storage_access_keys - .map(|k| Nibbles::from_h256_be(hash(&k.0))) + .map(|k| Nibbles::from_h256_be(hash(k.0))) .collect::>(), ); }; @@ -116,6 +121,11 @@ impl TxnInfo { || code_change; if state_write_occurred { + // Account creations are flagged to handle reverts. + if !all_accounts.contains(&hashed_addr) { + created_accounts.insert(hashed_addr); + } + if let Some(state_trie_writes) = nodes_used_by_txn.state_writes.get_mut(&hashed_addr) { @@ -168,10 +178,10 @@ impl TxnInfo { ContractCodeUsage::Read(c_hash) => { contract_code_accessed .entry(*c_hash) - .or_insert_with(|| code_hash_resolver.resolve(&c_hash)); + .or_insert_with(|| code_hash_resolver.resolve(c_hash)); } ContractCodeUsage::Write(c_bytes) => { - let c_hash = hash(&c_bytes); + let c_hash = hash(c_bytes); contract_code_accessed.insert(c_hash, c_bytes.clone()); code_hash_resolver.insert_code(c_hash, c_bytes.clone()); @@ -216,6 +226,7 @@ impl TxnInfo { txn_bytes, receipt_node_bytes, gas_used: txn.meta.gas_used, + created_accounts, }); } @@ -269,4 +280,5 @@ pub(crate) struct TxnMetaState { pub(crate) txn_bytes: Option>, pub(crate) receipt_node_bytes: Vec, pub(crate) gas_used: u64, + pub(crate) created_accounts: BTreeSet, } diff --git a/trace_decoder/src/typed_mpt.rs b/trace_decoder/src/typed_mpt.rs index 947727737..f42d7fa37 100644 --- a/trace_decoder/src/typed_mpt.rs +++ b/trace_decoder/src/typed_mpt.rs @@ -135,6 +135,7 @@ impl TriePath { pub fn from_hash(H256(bytes): H256) -> Self { Self::new(AsNibbles(bytes)).expect("32 bytes is 64 nibbles, which fits") } + #[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 fn from_txn_ix(txn_ix: usize) -> Self { TriePath::new(AsNibbles(rlp::encode(&txn_ix))).expect( "\ @@ -163,6 +164,7 @@ impl TriePath { } } +#[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 /// Per-block, `txn_ix -> [u8]`. /// /// See @@ -171,6 +173,7 @@ pub struct TransactionTrie { untyped: HashedPartialTrie, } +#[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 impl TransactionTrie { pub fn insert(&mut self, txn_ix: usize, val: Vec) -> Result>, Error> { let prev = self @@ -190,6 +193,7 @@ impl TransactionTrie { } } +#[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 /// Per-block, `txn_ix -> [u8]`. /// /// See @@ -198,6 +202,7 @@ pub struct ReceiptTrie { untyped: HashedPartialTrie, } +#[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 impl ReceiptTrie { pub fn insert(&mut self, txn_ix: usize, val: Vec) -> Result>, Error> { let prev = self @@ -300,6 +305,7 @@ impl StorageTrie { pub fn root(&self) -> H256 { self.untyped.hash() } + #[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 pub fn remove(&mut self, path: TriePath) -> Result>, Error> { self.untyped .delete(path.into_nibbles()) @@ -308,7 +314,7 @@ impl StorageTrie { pub fn as_hashed_partial_trie(&self) -> &mpt_trie::partial_trie::HashedPartialTrie { &self.untyped } - + #[allow(unused)] // TODO(0xaatif): https://github.com/0xPolygonZero/zk_evm/issues/275 pub fn as_mut_hashed_partial_trie_unchecked(&mut self) -> &mut HashedPartialTrie { &mut self.untyped } diff --git a/trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev.json b/trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev.json new file mode 100644 index 000000000..e94bfd458 --- /dev/null +++ b/trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev.json @@ -0,0 +1,325 @@ +[ + { + "block_trace": { + "trie_pre_images": { + "combined": { + "compact": "0x000397e4ae58e8d997dd2b19ed09ad9a66d1c0fd304d074e4a7bfb3f1fcc512a3e6303e3f965eb951555f4f5b98ab8ff7a6e33813bf9ac6830c1f8e5806e5563d580580338e34f9e0e4830343ba24f5fcf0eba28d79cb86397adfb16a0169ee7f018003605582003d2dbe83a6ba7fd75737c8d7453d984e7938ba7ae113d3da2ad7433061157b0084101055820039c0a91ba30d346a55890b1b07287d8aae35baa8c4068ef8f1de66084aca750084101055820032dee2834b372effea65d7c74ab9f3ac60ef271e846721aa8759a346a3b55400c182c4c033b2e3c9e69be1f3b8f45fc0219020303d2e57f615a47508c6e60935353428b9fc1cc75677a3eb8f5f73d61dd0aaff5f5055820021d99c6bec3aecbec962be74b25448511983b013c0876f6f4e6029773dfad61084101034d78166b48044fdc28ed22d2fd39c8df6f8aaa04cb71d3a17286856f6893ff830361d0d822132d4f46ea985e243ddfec94d3d12badf05efc100c2acaab3232979a05582002b3096c912adc7674ca92b68ddb3b0494e9b988fbef1bed7938e8fac4c2df7a0841010458613373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff01550003b42b3ff34cf94e9bbe576c7d3407125a4a78bc7ed3612b0859c3d54732184c04005820027b7c396774442700f076020d6320b11205bdfa1ed29bca4e6403a4ed13003e5820ae9e0c29f970fa4b19e4dd1e122f44e36e28b0366016bede9cad8ee2b9abc0ec00582002b38c731c4c7dcfa7fe43e88c29fc820b7a639725c025ad4d57a4ba4bfc7021582056138500dd56d246b423922d012878336234e86eb5163ddfe56ded875b6bb90b0219010803ae2be4c29fc3af59f45ec87171244d90f717dff0b4053c3f9e515f255ad21016037be6082e5131fd0ec3d0443048028ff5165919d8135b83eb9e871689af6151b800582002a35688244862fc757c3be1f20703dd54ed23a0500e2ba3a8c715f441dab6695820ee297c12fffb82a628f254b4e8b04d1068789f928e5ebbd53a9c6960f6a09ff500582002ac6e5f6b2ae78fed03998a21fffd6d0abe57ee36fa18fd8f390bf96881e1864466b12ee40219801003805f6a0a46b011fe00f83634ae7b5ee301e296ae987730717c0438d498fdb74303d08a05d0052c73e1436082038fba2562fcf36d5f1f6366027bf2c4c78218324703202eba034d3583cbc1fa600657c8bb355910c171c2e7174a016ee7f84a9982bb0352392a3a7f95abdd8c48bbaadf77e7be701e1a9c259a379f7837c6fdd77d569703327d2799bdf55eb20ae98ff3acac7a7e6d1bd5d5a763f529efb0872988c15e1f03241da08797ca89e9a4ae4d4d6fcbb1b22001c4aac25a1ef3e8b2edef94e3d62503f9b28e4f179934edd4393a00171269821a9a44893002137f760faa68fe8f19fb03bb4cbca0dff5a0525413795bd818ec527f9e385e8df4c101f7050f0cf93e61fa0363f140c8c24a1024f88d5c51292e514db03f1c7eec2a58e7c06d1ebeeea4ad7f03650d71b12779260726c804623311ab746d2bfa6162f236b8fd87234c0a63eb5e0332ee5d5e5496bb9209cd8bc651126d19b79b38b9fc12122ce469cfefd53099180219ffff05582002d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e420701186105582002401b4e97e67c4a6d8095979b4c1ecb9eaf5726fc8a12798975a7653e98087208410105582002c8bb92227ba91a2657f29c5498f5c5b07ae36369c8d9283444f477930c79be0841010391d9c76bfbc066e84f0b415c737ab8c477498701d920526db41690050cfade9905582002a5ac70a18399817ccbe8bd4d9c78115136cc61699d51af87608af520226c32084101055820029bd268aedc8dbb36db0a4664e17b83abcfd87e404901eee7bd5704a95064ee08410105582002a06a67e7fee9c938155c50e6cec9da70b66679e777da6f02149c6674cd910508410103d9240a9d2d5851d05a97ff3305334dfdb0101e1e321fc279d2bb3cad6afa8fc802197ffd03bb47debc67bc4630b38be2bcb4da207e5eeb900be8ebef5391e33f311259fe8f03f5973ddf4b6e95090d9f952ebba2f1efb05ecf7a8ca1108a51b83035168aedbb03724f631a141f6a338cc83620dba6cbc53e49035312204f3847a68e2d852fd67a0318385194f4abe12385937758d7599c7a11760dcfe3e3e2ba06ebfad44f10484e035750dfde66a7a051d429386138dc80cc40f94d0212ebbd6f3dd7950b994b7e6903be88e4724326382a8b56e2328eeef0ad51f18d5bae0e84296afe14c4028c4af903bcfafd70d9348d083c7d2e0e4a50b5012fc315c98366d3549628ce4ef1ee27d30558200216c0a47b12c20d5ac5c381464a89521d8b0c1a5cb328aeabb29b70bc3347d408410105582002b41c13f6e16fd2242a43b041cfd1f02cbb4cf06943d14365bb8f0a30ff507a0841010558200225fd832d00c025204251bf6c3f044d57347429973f8c48fd3d325f0e758f1b084c033b2e3c9fd0803ce8000000055820022e9dc15a35c1ab9d0ac4345b1f02fd8e8070883a33651c0c143b25827082680841010558200276da518a393dbd067dc72abfa08d475ed6447fca96d92ec3f9e7eba503ca61084102055820023db8611e8d0c159eb724d2aea72763dfb5a6909a8516467c79d0386d61a51108410103fd04efc67927fbaef3b8defd259a7f78b261bd8a0f93eedf78c0cb27c491083a0390c5d06de0e326fe782f9469df01c9028941571dffbbc643aed052feb1cff2f603ce35ec89408b73b495e2b3e0ef46d1ec796c7c2e6b05b8ad21547ffa391875c40558200203175444dc43cc33391c4c4010eac15d401b2eb5ffc7bc778abe372f28ce370841010219e75d031796617427e67ed10cdf8a72b02689a700ba71eb93186a1b120c9ad0b0e56eae03ebc052143e57028286ef115b03a8a7736efa26c165fcfffc807960b2bf91e1c003bffc43dfea9c9a304f9ae5154c60adff35f4c9a6e722a59d60cca4d97c4038bb030029f4fb3c18471948807d3163670fc396e8459d738d87a9aeb32444a6b9322d035740575999fde2ddd421a9f5907dfc4be5fc3f5f96d65240ae3b3b596d38465f055820028fd226a1d43fd9da3e823f52b7dbdfcb4e694ea884df54d86a14f708f43bd30848016345785d8a000005582002b693085beb21b0878c7e5fab7519ce0d6105354cf6744dbfb73e3745e929e4084101055820027f470df15c88b9beaf3fad72890a64f8851d01ece546b0c9fb3bdf92041a35084101055820029cb4b751333c144710961e20611eb00c783b77e8cb532c64307202fb109699084c033b2e3c9fd0803ce8000000035f4ca08c32e4a3997d0e94d8946e3d361ec5d0225d9cd85c6de8d572bb0a99c903faecf459527318d12fee2db8d85c54fc244d0207ba336a01e397593b801ae61f055820039bbcf08818ec3329e5769dff3fbdad66e6312a961acb32c1b203edf70aeba0084101031c13664b9096979e0a6a58919940b248687992af952308581eff9d0e8c14119a02194008033c4172d2125ea08dbe10db0a4a54290a622f10f24ba3a2460969ac13fcab7db3055820026a58207750197f48cb90864096850259845c2c8e90c74433325c0b144bf8bb08410105582002fa0eae268038cfa984647a1d0635beb86eda9fb7b500688f3189520cfa9ee50841010219fb710219ffff" + } + }, + "code_db": null, + "txn_info": [ + { + "traces": { + "0x6383f81bdc7c347888a54a8c6dd72f808221de21": { + "balance": "0x0" + }, + "0x3c0273033f6ad2ed3d768bb83b269d4dcf381fd1": { + "balance": "0x162e7fb2886c260", + "nonce": "0x1" + }, + "0x8943545177806ed17b9f23f0a21ee5948ecaa776": { + "balance": "0x33b2e3c9e6a196373797c7c" + } + }, + "meta": { + "byte_code": "0xf86a80843d44ddd9830186a08087d529ae9e8600009060005b600101804050630000000256008360306ba0b4615acfbef3163918e6907cfe40f0225ef4ce9ce3663ac905e01e56b307064ca03b2189980a28734c355d1b4da64cc8c4027806c5de077d7a84763a3db08a3db2", + "new_txn_trie_node_byte": "0xf86a80843d44ddd9830186a08087d529ae9e8600009060005b600101804050630000000256008360306ba0b4615acfbef3163918e6907cfe40f0225ef4ce9ce3663ac905e01e56b307064ca03b2189980a28734c355d1b4da64cc8c4027806c5de077d7a84763a3db08a3db2", + "new_receipt_trie_node_byte": "0xf9010980830186a0b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0", + "gas_used": 100000 + } + } + ] + }, + "other_data": { + "b_data": { + "b_meta": { + "block_beneficiary": "0x8943545177806ed17b9f23f0a21ee5948ecaa776", + "block_timestamp": "0x66b12fe0", + "block_number": "0x1c", + "block_difficulty": "0x0", + "block_random": "0x1c84d61f862e3937c259d3f998dac1381f170c18fcd63652db04f4eada8defc8", + "block_gaslimit": "0x1c9c380", + "block_chain_id": "0x301824", + "block_base_fee": "0x174e475", + "block_gas_used": "0x186a0", + "block_blob_gas_used": "0x0", + "block_excess_blob_gas": "0x0", + "parent_beacon_block_root": "0x287ecf202259331c4b437237cf469539abc2ab02d6ab3072f14a8523cd855a36", + "block_bloom": [ + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0", + "0x0" + ] + }, + "b_hashes": { + "prev_hashes": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x5c09356fd54924bd63d5bef3f0f334114d8cb34e545b98f6289115d996e40c82", + "0xc7c2166896d1e9a890bcdeb2ca8470ca7d020de136588d8a05edb8fdf6ad9ac3", + "0x5329cbde8e0b834329c353a5f95b49beed7fb692395838fd005c26a2146fcc49", + "0xe4c9847766b928037efe232abe211de3c2cc75254d8a2cde999c2c00682c82eb", + "0xb3f21feee05522028e2618ea8377f6a2a84ecec35fe3292ced387537e66f33e2", + "0xd209ac9bd40d44278a40bbebcda14234d00c17519242847224256ce3d054f236", + "0x89003258f6a8487f5b66efa320cfde14fabb3b904bbf6cd71a3869045d7b961e", + "0x369bd1e5568cc7270031694949fbce7a44b7fe8b41d23e48a43c8d2d2c76dc45", + "0x289a8ad22308f255c8831085473986eb119cb1fe931efddffbbc38a45ca21978", + "0x30302bbf676bd710268dd16aaee094293722f3ffbbaaa895c04e44cd6e617586", + "0xd527fd267764e4edd30e6b00997ba8dc8372ffb0011a550bd1cd90ae08b71c2d", + "0x25dee803de79dce71c8c69ebbdb785df3e9a702fea51e44dfbc5772602d579c6", + "0xaa1e00aa825a379627e2ad25494ef4df8746117516777c059a56189b439f160f", + "0x05998aee0a94a1641718cfeabef8be9c1ff2317d40ee6f6d556984e47806645f", + "0xba33e8ebb6967582ac6655ff3df8c853b7b9c8f1049fe428ba983ae0777acb01", + "0x12c849a7cd349cad36c8af763dcde0aad8599e379cd4eb10ba1db4f71b849485", + "0xe47d533ba58626f1cac70e4c3c0232dbeb82fad0a6a40ca72dda8109ef3f0ea4", + "0xc4328e04fc8b7ec9391e934f283b2b1c7aea53fb6d20c057ffc87bffeceb79bb", + "0x53ea70df099bd2917e3c92b227dddcd08ec9304e09fc890ba10bbec233fcb951", + "0x10efed26e262a50f58b785edcfc20f0a12a4dfc792e6d49ec41dfa59023e3cbd", + "0x26acd6026abf999eb2be60bcb83ddbb63321c2527a5b3a9ec00a57d28535dddf", + "0x4cc4863be89f71110bfae4adcedd6baffdbfc6bab79647f20efd70883d220e63", + "0xe9a0d90fcd20b37ce2a01b75801f3aab6a5a4916e5c6d2586df64d2c0e5ccf6d", + "0xdb18b431446c147511678da8c3974ed68917e76238c0058ea281684ee45aac4e", + "0x4c82a772a2ef771fc7e0b2fdc95a74c1c37629c434658f21ffcf7f05cd055450", + "0xf0b132b1881455ebeff23c2823ceeaf4cd919803d1f0d28a208a32c6ba9e2e75", + "0xf52f4745f69063ba2705aec5c7478eb1cbaf3d4ef82e15ffe221d2a2dc798e30", + "0x46df26e4fe1d2df293cf06fe02296c0c80aa33cb00b6a3ca68baff077aefd17e" + ], + "cur_hash": "0x92162ed5e309ee46bf55cb3a811d423e6a34c5003e9d73cfacc6014789f48917" + }, + "withdrawals": [] + }, + "checkpoint_state_trie_root": "0x106d584f6804109c493182d0bb8ef06380aea582090f4c2927276869a8d1e436" + } + } +] \ No newline at end of file diff --git a/trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev_header.json b/trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev_header.json new file mode 100644 index 000000000..abf62be05 --- /dev/null +++ b/trace_decoder/tests/data/witnesses/zero_jerigon/b28_dev_header.json @@ -0,0 +1,32 @@ +[ + { + "baseFeePerGas": "0x174e475", + "blobGasUsed": "0x0", + "difficulty": "0x0", + "excessBlobGas": "0x0", + "extraData": "0x", + "gasLimit": "0x1c9c380", + "gasUsed": "0x186a0", + "hash": "0x92162ed5e309ee46bf55cb3a811d423e6a34c5003e9d73cfacc6014789f48917", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "miner": "0x8943545177806ed17b9f23f0a21ee5948ecaa776", + "mixHash": "0x1c84d61f862e3937c259d3f998dac1381f170c18fcd63652db04f4eada8defc8", + "nonce": "0x0000000000000000", + "number": "0x1c", + "parentBeaconBlockRoot": "0x287ecf202259331c4b437237cf469539abc2ab02d6ab3072f14a8523cd855a36", + "parentHash": "0x46df26e4fe1d2df293cf06fe02296c0c80aa33cb00b6a3ca68baff077aefd17e", + "receiptsRoot": "0x777f1c1c378807634128348e4f0eeca6a0e7f516ea411690ca04266323f671a4", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x2b7", + "stateRoot": "0x1cc97e7468f7cfb76f239d373d9f5124d1055f72e400b6ba865ae4f0aa1abbbf", + "timestamp": "0x66b12fe0", + "totalDifficulty": "0x1", + "transactions": [ + "0xf7be24d19c8398bbbfc2238de4b3da9a9a2a645099de4601bfa2fadf70aac9da" + ], + "transactionsRoot": "0x75cd82907b1e556b0cb52d18449487629b2b82c769a37a4b60b1760bac90a734", + "uncles": [], + "withdrawals": [], + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + } +] \ No newline at end of file diff --git a/zero_bin/README.md b/zero_bin/README.md index 359830aeb..e97a2b2ee 100644 --- a/zero_bin/README.md +++ b/zero_bin/README.md @@ -87,13 +87,15 @@ Usage: leader [OPTIONS] Commands: stdio Reads input from stdin and writes output to stdout jerigon Reads input from a Jerigon node and writes output to stdout - native Reads input from a native node and writes output to stdout + native Reads input from a native node and writes output to stdout http Reads input from HTTP and writes output to a directory help Print this message or the help of the given subcommand(s) Options: -h, --help Print help (see a summary with '-h') + --version + Fetch the `evm_arithmetization` package version, build commit hash and build timestamp Paladin options: -t, --task-bus-routing-key @@ -366,6 +368,7 @@ cargo r --bin verifier -- --help Usage: verifier --file-path Options: + --version Fetch the `evm_arithmetization` package version, build commit hash and build timestamp -f, --file-path The file containing the proof to verify -h, --help Print help ``` @@ -386,11 +389,13 @@ cargo r --bin rpc -- --help Usage: rpc Commands: - fetch Fetch and generate prover input from the RPC endpoint - help Print this message or the help of the given subcommand(s) + fetch Fetch and generate prover input from the RPC endpoint + help Print this message or the help of the given subcommand(s) Options: -h, --help Print help + --version + Fetch the `evm_arithmetization` package version, build commit hash and build timestamp ``` Example: @@ -457,15 +462,20 @@ Finally, note that both of these testing scripts force proof generation to be se The trace decoder module has some basic regression tests, using the json witness data from the `trace_decoder/tests/data/witnesses` subdirectories. When needed (e.g. some block with corner-case discovered), additional input witness data should be generated using the following procedure: + 1. Run the `rpc` tool to fetch the block (or multiple blocks) witness: + ```sh cargo run --bin rpc fetch --rpc-url --start-block --end-block > ./b_.json ``` + 2. Download the header file for the block (or range of blocks), making the json array of headers: + ```sh file_name = "b__header.json" echo "[" > $file_name && cast rpc eth_getBlockByNumber "0x" 'false' --rpc-url >> $file_name && echo "]" >> $file_name ``` + Move the generated files to the appropriate subdirectory, and they will be automatically included in the test run. ## License diff --git a/zero_bin/common/Cargo.toml b/zero_bin/common/Cargo.toml index 7c24b21b4..d9880deb3 100644 --- a/zero_bin/common/Cargo.toml +++ b/zero_bin/common/Cargo.toml @@ -23,3 +23,10 @@ futures = { workspace = true } tokio = { workspace = true } alloy = { workspace = true } async-stream = { workspace = true } +cargo_metadata = { workspace = true } +vergen = { workspace = true } + +[build-dependencies] +cargo_metadata = { workspace = true } +vergen = { workspace = true } +anyhow = { workspace = true } diff --git a/zero_bin/leader/build.rs b/zero_bin/common/build.rs similarity index 56% rename from zero_bin/leader/build.rs rename to zero_bin/common/build.rs index 0adcbb347..c3e7b006d 100644 --- a/zero_bin/leader/build.rs +++ b/zero_bin/common/build.rs @@ -1,5 +1,15 @@ use anyhow::Context as _; +use vergen::{BuildBuilder, Emitter, RustcBuilder}; + fn main() -> anyhow::Result<()> { + let build_timestamp = BuildBuilder::default().build_timestamp(true).build()?; + let rust_commit_hash = RustcBuilder::default().commit_hash(true).build()?; + + Emitter::default() + .add_instructions(&build_timestamp)? + .add_instructions(&rust_commit_hash)? + .emit()?; + let meta = cargo_metadata::MetadataCommand::new() .exec() .context("failed to probe cargo-metadata")?; @@ -10,10 +20,11 @@ fn main() -> anyhow::Result<()> { .context("couldn't find evm_arithmetization package")? .version; println!( - "cargo::rustc-env=EVM_ARITHMETIZATION_PACKAGE_VERSION={}.{}.x", + "cargo::rustc-env=EVM_ARITHMETIZATION_PKG_VER={}.{}.x", // patch version change should not prompt circuits regeneration version.major, version.minor ); + Ok(()) } diff --git a/zero_bin/common/src/lib.rs b/zero_bin/common/src/lib.rs index 1b0b18e9b..5570a5d5f 100644 --- a/zero_bin/common/src/lib.rs +++ b/zero_bin/common/src/lib.rs @@ -3,3 +3,4 @@ pub mod debug_utils; pub mod fs; pub mod parsing; pub mod prover_state; +pub mod version; diff --git a/zero_bin/common/src/prover_state/persistence.rs b/zero_bin/common/src/prover_state/persistence.rs index 87eb7d1ae..750726696 100644 --- a/zero_bin/common/src/prover_state/persistence.rs +++ b/zero_bin/common/src/prover_state/persistence.rs @@ -109,7 +109,7 @@ impl DiskResource for BaseProverResource { "{}/{}_base_{}_{}", &relative_circuit_dir_path(), PROVER_STATE_FILE_PREFIX, - env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), + env!("EVM_ARITHMETIZATION_PKG_VER"), p.get_configuration_digest() ) } @@ -145,7 +145,7 @@ impl DiskResource for MonolithicProverResource { "{}/{}_monolithic_{}_{}", &relative_circuit_dir_path(), PROVER_STATE_FILE_PREFIX, - env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), + env!("EVM_ARITHMETIZATION_PKG_VER"), p.get_configuration_digest() ) } @@ -180,7 +180,7 @@ impl DiskResource for RecursiveCircuitResource { "{}/{}_{}_{}_{}", &relative_circuit_dir_path(), PROVER_STATE_FILE_PREFIX, - env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), + env!("EVM_ARITHMETIZATION_PKG_VER"), circuit_type.as_short_str(), size ) @@ -224,7 +224,7 @@ impl DiskResource for VerifierResource { "{}/{}_{}_{}", &relative_circuit_dir_path(), VERIFIER_STATE_FILE_PREFIX, - env::var("EVM_ARITHMETIZATION_PKG_VER").unwrap_or("NA".to_string()), + env!("EVM_ARITHMETIZATION_PKG_VER"), p.get_configuration_digest() ) } diff --git a/zero_bin/common/src/version.rs b/zero_bin/common/src/version.rs new file mode 100644 index 000000000..5dbbf7f9b --- /dev/null +++ b/zero_bin/common/src/version.rs @@ -0,0 +1,10 @@ +pub fn print_version( + evm_arithmetization_package_version: &str, + rustc_commit_hash: &str, + rustc_timestamp: &str, +) { + println!( + "evm_arithmetization Package Version: {}\nBuild Commit Hash: {}\nBuild Timestamp: {}", + evm_arithmetization_package_version, rustc_commit_hash, rustc_timestamp + ) +} diff --git a/zero_bin/leader/Cargo.toml b/zero_bin/leader/Cargo.toml index dfb0070b4..5d0881da1 100644 --- a/zero_bin/leader/Cargo.toml +++ b/zero_bin/leader/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true repository.workspace = true keywords.workspace = true categories.workspace = true +build = "../common/build.rs" [dependencies] paladin-core = { workspace = true } @@ -36,5 +37,6 @@ default = [] test_only = ["ops/test_only", "prover/test_only"] [build-dependencies] -cargo_metadata = "0.18.1" +cargo_metadata = { workspace = true } +vergen = { workspace = true } anyhow = { workspace = true } diff --git a/zero_bin/leader/src/main.rs b/zero_bin/leader/src/main.rs index f76e94300..611b4bc04 100644 --- a/zero_bin/leader/src/main.rs +++ b/zero_bin/leader/src/main.rs @@ -11,6 +11,7 @@ use paladin::runtime::Runtime; use proof_gen::proof_types::GeneratedBlockProof; use tracing::{info, warn}; use zero_bin_common::block_interval::BlockInterval; +use zero_bin_common::version; use crate::client::{client_main, ProofParams}; @@ -20,7 +21,7 @@ mod http; mod init; mod stdio; -const EVM_ARITH_VER_KEY: &str = "EVM_ARITHMETIZATION_PKG_VER"; +const EVM_ARITHMETIZATION_PKG_VER: &str = "EVM_ARITHMETIZATION_PKG_VER"; fn get_previous_proof(path: Option) -> Result> { if path.is_none() { @@ -39,17 +40,27 @@ async fn main() -> Result<()> { load_dotenvy_vars_if_present(); init::tracing(); - if env::var_os(EVM_ARITH_VER_KEY).is_none() { + if env::var_os(EVM_ARITHMETIZATION_PKG_VER).is_none() { // Safety: // - we're early enough in main that nothing else should race unsafe { env::set_var( - EVM_ARITH_VER_KEY, - // see build.rs - env!("EVM_ARITHMETIZATION_PACKAGE_VERSION"), + EVM_ARITHMETIZATION_PKG_VER, + env!("EVM_ARITHMETIZATION_PKG_VER"), ); } - }; + } + + let args: Vec = env::args().collect(); + + if args.contains(&"--version".to_string()) { + version::print_version( + env!("EVM_ARITHMETIZATION_PKG_VER"), + env!("VERGEN_RUSTC_COMMIT_HASH"), + env!("VERGEN_BUILD_TIMESTAMP"), + ); + return Ok(()); + } let args = cli::Cli::parse(); if let paladin::config::Runtime::InMemory = args.paladin.runtime { @@ -60,8 +71,6 @@ async fn main() -> Result<()> { .initialize()?; } - let runtime = Runtime::from_config(&args.paladin, register()).await?; - match args.command { Command::Stdio { previous_proof, @@ -69,6 +78,7 @@ async fn main() -> Result<()> { batch_size, save_inputs_on_error, } => { + let runtime = Runtime::from_config(&args.paladin, register()).await?; let previous_proof = get_previous_proof(previous_proof)?; stdio::stdio_main( runtime, @@ -86,6 +96,7 @@ async fn main() -> Result<()> { batch_size, save_inputs_on_error, } => { + let runtime = Runtime::from_config(&args.paladin, register()).await?; // check if output_dir exists, is a directory, and is writable let output_dir_metadata = std::fs::metadata(&output_dir); if output_dir_metadata.is_err() { @@ -120,6 +131,7 @@ async fn main() -> Result<()> { backoff, max_retries, } => { + let runtime = Runtime::from_config(&args.paladin, register()).await?; let previous_proof = get_previous_proof(previous_proof)?; let mut block_interval = BlockInterval::new(&block_interval)?; diff --git a/zero_bin/rpc/Cargo.toml b/zero_bin/rpc/Cargo.toml index 6724c16fe..14f447cef 100644 --- a/zero_bin/rpc/Cargo.toml +++ b/zero_bin/rpc/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true repository.workspace = true keywords.workspace = true categories.workspace = true +build = "../common/build.rs" [dependencies] __compat_primitive_types = { workspace = true } @@ -30,3 +31,8 @@ url = { workspace = true } compat = { workspace = true } zero_bin_common = { workspace = true } prover = { workspace = true } + +[build-dependencies] +cargo_metadata = { workspace = true } +vergen = { workspace = true } +anyhow = { workspace = true } diff --git a/zero_bin/rpc/src/main.rs b/zero_bin/rpc/src/main.rs index 197e387de..ee1ed08e0 100644 --- a/zero_bin/rpc/src/main.rs +++ b/zero_bin/rpc/src/main.rs @@ -1,4 +1,4 @@ -use std::io; +use std::{env, io}; use alloy::rpc::types::eth::BlockId; use clap::{Parser, ValueHint}; @@ -7,6 +7,7 @@ use rpc::{retry::build_http_retry_provider, RpcType}; use tracing_subscriber::{prelude::*, EnvFilter}; use url::Url; use zero_bin_common::block_interval::BlockInterval; +use zero_bin_common::version; #[derive(Parser)] pub enum Cli { @@ -78,6 +79,16 @@ impl Cli { #[tokio::main] async fn main() -> anyhow::Result<()> { + let args: Vec = env::args().collect(); + if args.contains(&"--version".to_string()) { + version::print_version( + env!("EVM_ARITHMETIZATION_PKG_VER"), + env!("VERGEN_RUSTC_COMMIT_HASH"), + env!("VERGEN_BUILD_TIMESTAMP"), + ); + return Ok(()); + } + tracing_subscriber::Registry::default() .with( tracing_subscriber::fmt::layer() diff --git a/zero_bin/verifier/Cargo.toml b/zero_bin/verifier/Cargo.toml index 39968b4a6..ab9e5068f 100644 --- a/zero_bin/verifier/Cargo.toml +++ b/zero_bin/verifier/Cargo.toml @@ -3,6 +3,7 @@ name = "verifier" authors = ["Polygon Zero "] version = "0.1.0" edition = "2021" +build = "../common/build.rs" [dependencies] clap = { workspace = true } @@ -16,3 +17,8 @@ proof_gen = { workspace = true } # Local dependencies zero_bin_common = { path = "../common" } + +[build-dependencies] +cargo_metadata = { workspace = true } +vergen = { workspace = true } +anyhow = { workspace = true } diff --git a/zero_bin/verifier/src/main.rs b/zero_bin/verifier/src/main.rs index 0c072fed9..e14ad7827 100644 --- a/zero_bin/verifier/src/main.rs +++ b/zero_bin/verifier/src/main.rs @@ -1,3 +1,4 @@ +use std::env; use std::fs::File; use anyhow::Result; @@ -6,6 +7,7 @@ use dotenvy::dotenv; use proof_gen::proof_types::GeneratedBlockProof; use serde_json::Deserializer; use tracing::info; +use zero_bin_common::version; mod cli; mod init; @@ -14,7 +16,18 @@ fn main() -> Result<()> { dotenv().ok(); init::tracing(); + let args: Vec = env::args().collect(); + if args.contains(&"--version".to_string()) { + version::print_version( + env!("EVM_ARITHMETIZATION_PKG_VER"), + env!("VERGEN_RUSTC_COMMIT_HASH"), + env!("VERGEN_BUILD_TIMESTAMP"), + ); + return Ok(()); + } + let args = cli::Cli::parse(); + let file = File::open(args.file_path)?; let des = &mut Deserializer::from_reader(&file); let input_proofs: Vec = serde_path_to_error::deserialize(des)?; diff --git a/zero_bin/worker/Cargo.toml b/zero_bin/worker/Cargo.toml index 16d55ef29..3a146c90e 100644 --- a/zero_bin/worker/Cargo.toml +++ b/zero_bin/worker/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true repository.workspace = true keywords.workspace = true categories.workspace = true +build = "../common/build.rs" [dependencies] paladin-core = { workspace = true } @@ -22,3 +23,8 @@ zero_bin_common = { workspace = true } [target.'cfg(not(target_env = "msvc"))'.dependencies] jemallocator = "0.5.4" + +[build-dependencies] +cargo_metadata = { workspace = true } +vergen = { workspace = true } +anyhow = { workspace = true } diff --git a/zero_bin/worker/src/main.rs b/zero_bin/worker/src/main.rs index 4fb8675ff..2358401f4 100644 --- a/zero_bin/worker/src/main.rs +++ b/zero_bin/worker/src/main.rs @@ -1,9 +1,12 @@ +use std::env; + use anyhow::Result; use clap::Parser; use dotenvy::dotenv; use ops::register; use paladin::runtime::WorkerRuntime; use zero_bin_common::prover_state::cli::CliProverStateConfig; +use zero_bin_common::version; mod init; @@ -13,7 +16,7 @@ mod init; #[global_allocator] static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; -#[derive(Parser, Debug)] +#[derive(Parser)] struct Cli { #[clap(flatten)] paladin: paladin::config::Config, @@ -23,6 +26,16 @@ struct Cli { #[tokio::main] async fn main() -> Result<()> { + let args: Vec = env::args().collect(); + if args.contains(&"--version".to_string()) { + version::print_version( + env!("EVM_ARITHMETIZATION_PKG_VER"), + env!("VERGEN_RUSTC_COMMIT_HASH"), + env!("VERGEN_BUILD_TIMESTAMP"), + ); + return Ok(()); + } + dotenv().ok(); init::tracing(); let args = Cli::parse();