From 912d386947f82e3fc3d0ced55f85ca13d3a16778 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 19 Sep 2024 14:51:04 +0200 Subject: [PATCH 01/60] Add type2 preninitialization --- evm_arithmetization/Cargo.toml | 1 + .../src/generation/linked_list.rs | 2 + evm_arithmetization/src/generation/mod.rs | 29 ++- evm_arithmetization/src/generation/mpt.rs | 32 ++- evm_arithmetization/src/generation/state.rs | 43 +++- evm_arithmetization/src/memory/segments.rs | 231 +++++++++++++++++- smt_trie/src/smt.rs | 144 ++++++++++- 7 files changed, 449 insertions(+), 33 deletions(-) diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index ffdb8d2f5..d27f4fbd6 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -62,6 +62,7 @@ default = ["eth_mainnet"] asmtools = ["hex"] polygon_pos = [] cdk_erigon = ["smt_trie"] +type2 = ["smt_trie"] eth_mainnet = [] [[bin]] diff --git a/evm_arithmetization/src/generation/linked_list.rs b/evm_arithmetization/src/generation/linked_list.rs index fbe0e4965..44fea8f34 100644 --- a/evm_arithmetization/src/generation/linked_list.rs +++ b/evm_arithmetization/src/generation/linked_list.rs @@ -11,6 +11,7 @@ use crate::witness::errors::ProverInputError::InvalidInput; pub const ACCOUNTS_LINKED_LIST_NODE_SIZE: usize = 4; pub const STORAGE_LINKED_LIST_NODE_SIZE: usize = 5; +pub const STATE_LINKED_LIST_NODE_SIZE: usize = 4; pub(crate) trait LinkedListType {} #[derive(Clone)] @@ -26,6 +27,7 @@ impl LinkedListType for Bounded {} pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; +pub(crate) type StateLinkedList<'a> = LinkedList<'a, STATE_LINKED_LIST_NODE_SIZE>; // A linked list implemented using a vector `access_list_mem`. // In this representation, the values of nodes are stored in the range diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 9c7625d2b..d1a127816 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -17,6 +17,8 @@ use GlobalMetadata::{ ReceiptTrieRootDigestAfter, ReceiptTrieRootDigestBefore, StateTrieRootDigestAfter, StateTrieRootDigestBefore, TransactionTrieRootDigestAfter, TransactionTrieRootDigestBefore, }; +#[cfg(feature = "cdk_erigon")] +use smt_trie::smt::Smt; use crate::all_stark::{AllStark, NUM_TABLES}; use crate::cpu::columns::CpuColumnsView; @@ -158,12 +160,21 @@ pub struct TrimmedGenerationInputs { pub block_hashes: BlockHashes, } +#[cfg(feature = "cdk_erigon")] +type SmtTrie = smt_trie::smt::Smt; + +#[cfg(feature = "cdk_erigon")] +pub type TrieInputs = AbstractTrieInputs; + +#[cfg(not(feature = "cdk_erigon"))] +pub type TrieInputs = AbstractTrieInputs; + #[derive(Clone, Debug, Deserialize, Serialize, Default)] -pub struct TrieInputs { +pub struct AbstractTrieInputs { /// A partial version of the state trie prior to these transactions. It /// should include all nodes that will be accessed by these - /// transactions. - pub state_trie: HashedPartialTrie, + /// transactions. + pub state_trie: T, /// A partial version of the transaction trie prior to these transactions. /// It should include all nodes that will be accessed by these @@ -178,15 +189,21 @@ pub struct TrieInputs { /// A partial version of each storage trie prior to these transactions. It /// should include all storage tries, and nodes therein, that will be /// accessed by these transactions. - pub storage_tries: Vec<(H256, HashedPartialTrie)>, + pub storage_tries: Vec<(H256, T)>, } +#[cfg(feature = "cdk_erigon")] +pub type TrimmedTrieInputs = AbstractTrimmedTrieInputs; + +#[cfg(not(feature = "cdk_erigon"))] +pub type TrimmedTrieInputs = AbstractTrimmedTrieInputs; + #[derive(Clone, Debug, Deserialize, Serialize, Default)] -pub struct TrimmedTrieInputs { +pub struct AbstractTrimmedTrieInputs { /// A partial version of the state trie prior to these transactions. It /// should include all nodes that will be accessed by these /// transactions. - pub state_trie: HashedPartialTrie, + pub state_trie: T, /// A partial version of each storage trie prior to these transactions. It /// should include all storage tries, and nodes therein, that will be /// accessed by these transactions. diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 85f85e75f..100fc03c6 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -527,12 +527,10 @@ where } /// A type alias used to gather: -/// - the trie root pointers for all tries /// - the vector of state trie leaves /// - the vector of storage trie leaves /// - the `TrieData` segment's memory content -type TriePtrsLinkedLists = ( - TrieRootPtrs, +type LinkedListsAndTrieData = ( Vec>, Vec>, Vec>, @@ -542,13 +540,12 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( accounts_pointers: &mut BTreeMap, storage_pointers: &mut BTreeMap<(U256, U256), usize>, trie_inputs: &TrieInputs, -) -> Result { +) -> Result { let mut state_leaves = empty_list_mem::(Segment::AccountsLinkedList).to_vec(); let mut storage_leaves = empty_list_mem::(Segment::StorageLinkedList).to_vec(); let mut trie_data = vec![Some(U256::zero())]; - let storage_tries_by_state_key = trie_inputs .storage_tries .iter() @@ -559,14 +556,6 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( }) .collect(); - let txn_root_ptr = load_mpt(&trie_inputs.transactions_trie, &mut trie_data, &|rlp| { - let mut parsed_txn = vec![U256::from(rlp.len())]; - parsed_txn.extend(rlp.iter().copied().map(U256::from)); - Ok(parsed_txn) - })?; - - let receipt_root_ptr = load_mpt(&trie_inputs.receipts_trie, &mut trie_data, &parse_receipts)?; - get_state_and_storage_leaves( &trie_inputs.state_trie, empty_nibbles(), @@ -579,11 +568,6 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( )?; Ok(( - TrieRootPtrs { - state_root_ptr: None, - txn_root_ptr, - receipt_root_ptr, - }, state_leaves, storage_leaves, trie_data, @@ -612,6 +596,18 @@ pub(crate) fn load_state_mpt( ) } +pub(crate) fn load_transactions_mpt(transactions_trie: &HashedPartialTrie, trie_data: &mut Vec>) { + load_mpt(transactions_trie, trie_data, &|rlp| { + let mut parsed_txn = vec![U256::from(rlp.len())]; + parsed_txn.extend(rlp.iter().copied().map(U256::from)); + Ok(parsed_txn) + })?; +} + +pub(crate) fn load_receipts_mpt(receipts_trie: &HashedPartialTrie, trie_data: &mut Vec>) { + load_mpt(receipts_trie, trie_data, &parse_receipts)?; +} + pub mod transaction_testing { use ethereum_types::H160; diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index b094c15f9..f62ad9067 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -39,6 +39,8 @@ use crate::witness::transition::{ }; use crate::witness::util::{fill_channel_with_value, stack_peek}; use crate::{arithmetic, keccak, logic}; +use crate::generation::mpt::{load_transactions_mpt, load_receipts_mpt}; +use crate::generation::linked_list::{empty_list_mem, STATE_LINKED_LIST_NODE_SIZE}; /// A State is either an `Interpreter` (used for tests and jumpdest analysis) or /// a `GenerationState`. @@ -392,15 +394,29 @@ impl GenerationState { &mut self, trie_inputs: &TrieInputs, ) -> TrieRootPtrs { + let mut trie_data = vec![]; + if cfg!(not(feature = "cdk_erigon")) { + trie_data = self.preinitialize_linked_lists_and_get_trie_data(trie_inputs); + } else { + trie_data = self.preinitialize_linked_lists_and_get_smt_data(trie_inputs); + } + + let trie_root_ptrs = TrieRootPtrs { + state_root_ptr: None, + txn_root_ptr : load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data), + receipt_root_ptr: load_receipts_mpt(&trie_inputs.transactions_trie, &mut trie_data), + }; + } + + fn preinitialize_linked_lists_and_get_trie_data(&mut self, trie_inputs: &super::AbstractTrieInputs) -> Vec> { let generation_state = self.get_mut_generation_state(); - let (trie_roots_ptrs, state_leaves, storage_leaves, trie_data) = + let (state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( &mut generation_state.accounts_pointers, &mut generation_state.storage_pointers, trie_inputs, ) .expect("Invalid MPT data for preinitialization"); - self.memory.insert_preinitialized_segment( Segment::AccountsLinkedList, crate::witness::memory::MemorySegmentState { @@ -417,8 +433,27 @@ impl GenerationState { Segment::TrieData, crate::witness::memory::MemorySegmentState { content: trie_data }, ); - - trie_roots_ptrs + trie_data + } + + fn preinitialize_linked_lists_and_get_smt_data( + &mut self, + trie_inputs: &TrieInputs, + ) -> Vec> { + let generation_state = self.get_mut_generation_state(); + let mut state_linked_list_data = + empty_list_mem::(Segment::StateLinkedList).to_vec(); + let smt_data = trie_inputs.state_trie.serialize_with_linked_lists(&mut state_linked_list_data); + self.memory.insert_preinitialized_segment( + Segment::StateLinkedList, + crate::witness::memory::MemorySegmentState { + content: state_linked_list_data, + }, + ); + self.memory.insert_preinitialized_segment( + Segment::TrieData, + crate::witness::memory::MemorySegmentState { content: smt_data }, + ); } pub(crate) fn new( diff --git a/evm_arithmetization/src/memory/segments.rs b/evm_arithmetization/src/memory/segments.rs index e1b6678f6..a11ec122f 100644 --- a/evm_arithmetization/src/memory/segments.rs +++ b/evm_arithmetization/src/memory/segments.rs @@ -2,11 +2,12 @@ use serde::{Deserialize, Serialize}; pub(crate) const SEGMENT_SCALING_FACTOR: usize = 32; +#[cfg(not(feature = "cdk_erigon"))] +#[allow(clippy::enum_clike_unportable_variant)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, Serialize, Deserialize)] /// This contains all the existing memory segments. The values in the enum are /// shifted by 32 bits to allow for convenient address components (context / /// segment / virtual) bundling in the kernel. -#[allow(clippy::enum_clike_unportable_variant)] -#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, Serialize, Deserialize)] pub(crate) enum Segment { /// Contains EVM bytecode. // The Kernel has optimizations relying on the Code segment being 0. @@ -88,22 +89,115 @@ pub(crate) enum Segment { TxnBlobVersionedHashes = 38 << SEGMENT_SCALING_FACTOR, } +#[cfg(feature = "cdk_erigon")] +#[allow(clippy::enum_clike_unportable_variant)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, Serialize, Deserialize)] +pub(crate) enum Segment { + /// Contains EVM bytecode. + // The Kernel has optimizations relying on the Code segment being 0. + // This shouldn't be changed! + Code = 0, + /// The program stack. + Stack = 1 << SEGMENT_SCALING_FACTOR, + /// Main memory, owned by the contract code. + MainMemory = 2 << SEGMENT_SCALING_FACTOR, + /// Data passed to the current context by its caller. + Calldata = 3 << SEGMENT_SCALING_FACTOR, + /// Data returned to the current context by its latest callee. + Returndata = 4 << SEGMENT_SCALING_FACTOR, + /// A segment which contains a few fixed-size metadata fields, such as the + /// caller's context, or the size of `CALLDATA` and `RETURNDATA`. + GlobalMetadata = 5 << SEGMENT_SCALING_FACTOR, + ContextMetadata = 6 << SEGMENT_SCALING_FACTOR, + /// General purpose kernel memory, used by various kernel functions. + /// In general, calling a helper function can result in this memory being + /// clobbered. + KernelGeneral = 7 << SEGMENT_SCALING_FACTOR, + /// Segment to hold account code for opcodes like `CODESIZE, CODECOPY,...`. + KernelAccountCode = 8 << SEGMENT_SCALING_FACTOR, + /// Contains normalized transaction fields; see `NormalizedTxnField`. + TxnFields = 9 << SEGMENT_SCALING_FACTOR, + /// Contains the data field of a transaction. + TxnData = 10 << SEGMENT_SCALING_FACTOR, + /// A buffer used to hold raw RLP data. + RlpRaw = 11 << SEGMENT_SCALING_FACTOR, + /// Contains all trie data. It is owned by the kernel, so it only lives on + /// context 0. + TrieData = 12 << SEGMENT_SCALING_FACTOR, + ShiftTable = 13 << SEGMENT_SCALING_FACTOR, + JumpdestBits = 14 << SEGMENT_SCALING_FACTOR, + EcdsaTable = 15 << SEGMENT_SCALING_FACTOR, + BnWnafA = 16 << SEGMENT_SCALING_FACTOR, + BnWnafB = 17 << SEGMENT_SCALING_FACTOR, + BnTableQ = 18 << SEGMENT_SCALING_FACTOR, + BnPairing = 19 << SEGMENT_SCALING_FACTOR, + /// List of addresses that have been accessed in the current transaction. + AccessedAddresses = 20 << SEGMENT_SCALING_FACTOR, + /// List of storage keys that have been accessed in the current transaction. + AccessedStorageKeys = 21 << SEGMENT_SCALING_FACTOR, + /// List of addresses that have called SELFDESTRUCT in the current + /// transaction. + SelfDestructList = 22 << SEGMENT_SCALING_FACTOR, + /// Contains the bloom filter of a transaction. + TxnBloom = 23 << SEGMENT_SCALING_FACTOR, + /// Contains the bloom filter present in the block header. + GlobalBlockBloom = 24 << SEGMENT_SCALING_FACTOR, + /// List of log pointers pointing to the LogsData segment. + Logs = 25 << SEGMENT_SCALING_FACTOR, + LogsData = 26 << SEGMENT_SCALING_FACTOR, + /// Journal of state changes. List of pointers to `JournalData`. Length in + /// `GlobalMetadata`. + Journal = 27 << SEGMENT_SCALING_FACTOR, + JournalData = 28 << SEGMENT_SCALING_FACTOR, + JournalCheckpoints = 29 << SEGMENT_SCALING_FACTOR, + /// List of addresses that have been touched in the current transaction. + TouchedAddresses = 30 << SEGMENT_SCALING_FACTOR, + /// List of checkpoints for the current context. Length in + /// `ContextMetadata`. + ContextCheckpoints = 31 << SEGMENT_SCALING_FACTOR, + /// List of 256 previous block hashes. + BlockHashes = 32 << SEGMENT_SCALING_FACTOR, + /// Segment storing the registers before/after the current execution, + /// as well as `exit_kernel` for the `registers_before`, in that order. + RegistersStates = 33 << SEGMENT_SCALING_FACTOR, + /// List of accounts in the state trie, + StateLinkedList = 34 << SEGMENT_SCALING_FACTOR, + // The transient storage of the current transaction. + TransientStorage = 35 << SEGMENT_SCALING_FACTOR, + /// List of contracts which have been created during the current + /// transaction. + CreatedContracts = 36 << SEGMENT_SCALING_FACTOR, + /// Blob versioned hashes specified in a type-3 transaction. + TxnBlobVersionedHashes = 37 << SEGMENT_SCALING_FACTOR, +} + // These segments are not zero-initialized. +#[cfg(not(feature = "cdk_erigon"))] pub(crate) const PREINITIALIZED_SEGMENTS_INDICES: [usize; 4] = [ Segment::Code.unscale(), Segment::TrieData.unscale(), Segment::AccountsLinkedList.unscale(), Segment::StorageLinkedList.unscale(), ]; +#[cfg(feature = "cdk_erigon")] +pub(crate) const PREINITIALIZED_SEGMENTS_INDICES: [usize; 3] = [ + Segment::Code.unscale(), + Segment::TrieData.unscale(), + Segment::StateLinkedList.unscale(), +]; impl Segment { + #[cfg(not(feature = "cdk_erigon"))] pub(crate) const COUNT: usize = 39; + #[cfg(feature = "cdk_erigon")] + pub(crate) const COUNT: usize = 38; /// Unscales this segment by `SEGMENT_SCALING_FACTOR`. pub(crate) const fn unscale(&self) -> usize { *self as usize >> SEGMENT_SCALING_FACTOR } + #[cfg(not(feature = "cdk_erigon"))] pub(crate) const fn all() -> [Self; Self::COUNT] { [ Self::Code, @@ -147,8 +241,52 @@ impl Segment { Self::TxnBlobVersionedHashes, ] } + #[cfg(feature = "cdk_erigon")] + pub(crate) const fn all() -> [Self; Self::COUNT] { + [ + Self::Code, + Self::Stack, + Self::MainMemory, + Self::Calldata, + Self::Returndata, + Self::GlobalMetadata, + Self::ContextMetadata, + Self::KernelGeneral, + Self::KernelAccountCode, + Self::TxnFields, + Self::TxnData, + Self::RlpRaw, + Self::TrieData, + Self::ShiftTable, + Self::JumpdestBits, + Self::EcdsaTable, + Self::BnWnafA, + Self::BnWnafB, + Self::BnTableQ, + Self::BnPairing, + Self::AccessedAddresses, + Self::AccessedStorageKeys, + Self::SelfDestructList, + Self::TxnBloom, + Self::GlobalBlockBloom, + Self::Logs, + Self::LogsData, + Self::Journal, + Self::JournalData, + Self::JournalCheckpoints, + Self::TouchedAddresses, + Self::ContextCheckpoints, + Self::BlockHashes, + Self::RegistersStates, + Self::StateLinkedList, + Self::TransientStorage, + Self::CreatedContracts, + Self::TxnBlobVersionedHashes, + ] + } /// The variable name that gets passed into kernel assembly code. + #[cfg(not(feature = "cdk_erigon"))] pub(crate) const fn var_name(&self) -> &'static str { match self { Segment::Code => "SEGMENT_CODE", @@ -193,6 +331,51 @@ impl Segment { } } + #[cfg(feature = "cdk_erigon")] + pub(crate) const fn var_name(&self) -> &'static str { + match self { + Segment::Code => "SEGMENT_CODE", + Segment::Stack => "SEGMENT_STACK", + Segment::MainMemory => "SEGMENT_MAIN_MEMORY", + Segment::Calldata => "SEGMENT_CALLDATA", + Segment::Returndata => "SEGMENT_RETURNDATA", + Segment::GlobalMetadata => "SEGMENT_GLOBAL_METADATA", + Segment::ContextMetadata => "SEGMENT_CONTEXT_METADATA", + Segment::KernelGeneral => "SEGMENT_KERNEL_GENERAL", + Segment::KernelAccountCode => "SEGMENT_KERNEL_ACCOUNT_CODE", + Segment::TxnFields => "SEGMENT_NORMALIZED_TXN", + Segment::TxnData => "SEGMENT_TXN_DATA", + Segment::RlpRaw => "SEGMENT_RLP_RAW", + Segment::TrieData => "SEGMENT_TRIE_DATA", + Segment::ShiftTable => "SEGMENT_SHIFT_TABLE", + Segment::JumpdestBits => "SEGMENT_JUMPDEST_BITS", + Segment::EcdsaTable => "SEGMENT_ECDSA_TABLE", + Segment::BnWnafA => "SEGMENT_BN_WNAF_A", + Segment::BnWnafB => "SEGMENT_BN_WNAF_B", + Segment::BnTableQ => "SEGMENT_BN_TABLE_Q", + Segment::BnPairing => "SEGMENT_BN_PAIRING", + Segment::AccessedAddresses => "SEGMENT_ACCESSED_ADDRESSES", + Segment::AccessedStorageKeys => "SEGMENT_ACCESSED_STORAGE_KEYS", + Segment::SelfDestructList => "SEGMENT_SELFDESTRUCT_LIST", + Segment::TxnBloom => "SEGMENT_TXN_BLOOM", + Segment::GlobalBlockBloom => "SEGMENT_GLOBAL_BLOCK_BLOOM", + Segment::Logs => "SEGMENT_LOGS", + Segment::LogsData => "SEGMENT_LOGS_DATA", + Segment::Journal => "SEGMENT_JOURNAL", + Segment::JournalData => "SEGMENT_JOURNAL_DATA", + Segment::JournalCheckpoints => "SEGMENT_JOURNAL_CHECKPOINTS", + Segment::TouchedAddresses => "SEGMENT_TOUCHED_ADDRESSES", + Segment::ContextCheckpoints => "SEGMENT_CONTEXT_CHECKPOINTS", + Segment::BlockHashes => "SEGMENT_BLOCK_HASHES", + Segment::RegistersStates => "SEGMENT_REGISTERS_STATES", + Segment::StateLinkedList => "SEGMENT_STATE_LINKED_LIST", + Segment::TransientStorage => "SEGMENT_TRANSIENT_STORAGE", + Segment::CreatedContracts => "SEGMENT_CREATED_CONTRACTS", + Segment::TxnBlobVersionedHashes => "SEGMENT_TXN_BLOB_VERSIONED_HASHES", + } + } + + #[cfg(not(feature = "cdk_erigon"))] pub(crate) const fn bit_range(&self) -> usize { match self { Segment::Code => 8, @@ -236,4 +419,48 @@ impl Segment { Segment::TxnBlobVersionedHashes => 256, } } + + #[cfg(feature = "cdk_erigon")] + pub(crate) const fn bit_range(&self) -> usize { + match self { + Segment::Code => 8, + Segment::Stack => 256, + Segment::MainMemory => 8, + Segment::Calldata => 8, + Segment::Returndata => 8, + Segment::GlobalMetadata => 256, + Segment::ContextMetadata => 256, + Segment::KernelGeneral => 256, + Segment::KernelAccountCode => 8, + Segment::TxnFields => 256, + Segment::TxnData => 8, + Segment::RlpRaw => 8, + Segment::TrieData => 256, + Segment::ShiftTable => 256, + Segment::JumpdestBits => 1, + Segment::EcdsaTable => 256, + Segment::BnWnafA => 8, + Segment::BnWnafB => 8, + Segment::BnTableQ => 256, + Segment::BnPairing => 256, + Segment::AccessedAddresses => 256, + Segment::AccessedStorageKeys => 256, + Segment::SelfDestructList => 256, + Segment::TxnBloom => 8, + Segment::GlobalBlockBloom => 256, + Segment::Logs => 256, + Segment::LogsData => 256, + Segment::Journal => 256, + Segment::JournalData => 256, + Segment::JournalCheckpoints => 256, + Segment::TouchedAddresses => 256, + Segment::ContextCheckpoints => 256, + Segment::BlockHashes => 256, + Segment::RegistersStates => 256, + Segment::StateLinkedList => 256, + Segment::TransientStorage => 256, + Segment::CreatedContracts => 256, + Segment::TxnBlobVersionedHashes => 256, + } + } } diff --git a/smt_trie/src/smt.rs b/smt_trie/src/smt.rs index 356c8c3e9..318f2c927 100644 --- a/smt_trie/src/smt.rs +++ b/smt_trie/src/smt.rs @@ -1,13 +1,14 @@ #![allow(clippy::needless_range_loop)] use std::borrow::Borrow; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use ethereum_types::U256; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::{Field, PrimeField64}; use plonky2::hash::poseidon::{Poseidon, PoseidonHash}; use plonky2::plonk::config::Hasher; +use serde::{Deserialize, Serialize}; use crate::bits::Bits; use crate::db::Db; @@ -20,8 +21,9 @@ pub(crate) const INTERNAL_TYPE: u8 = 1; pub(crate) const LEAF_TYPE: u8 = 2; pub type F = GoldilocksField; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Key(pub [F; 4]); + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Node(pub [F; 12]); pub type Hash = PoseidonHash; @@ -82,7 +84,7 @@ impl Node { /// subtree. Internal nodes hold the hashes of their children. /// The root is the hash of the root internal node. /// Leaves are hashed using a prefix of 0, internal nodes using a prefix of 1. -#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] pub struct Smt { pub db: D, pub kv_store: HashMap, @@ -438,10 +440,59 @@ impl Smt { v } + pub fn serialize_and_prune_with_linked_lists + ( + &self, + keys: I, + linked_list_mem: &mut Vec>, + state_ptrs: &mut BTreeMap, + ) -> Vec> + where + K: Borrow, + I: IntoIterator, + { + let mut smt_mem = vec![Some(U256::zero()); 2]; // For empty hash node. + let key = Key(self.root.elements); + + let mut keys_to_include = HashSet::new(); + for key in keys.into_iter() { + let mut bits = key.borrow().split(); + loop { + keys_to_include.insert(bits); + if bits.is_empty() { + break; + } + bits.pop_next_bit(); + } + } + + serialize_with_linked_lists::<_, O>( + self, + key, + Bits::empty(), + &keys_to_include, + &mut smt_mem, + linked_list_mem, + state_ptrs, + ); + if smt_mem.len() == 2 { + smt_mem.extend([Some(U256::zero()); 2]); + } + smt_mem + } + pub fn serialize(&self) -> Vec { // Include all keys. self.serialize_and_prune(self.kv_store.keys()) } + + pub fn serialize_with_linked_lists( + &self, + linked_list_mem: &mut Vec>, + state_ptrs: &mut BTreeMap, + ) -> Vec> { + self.serialize_and_prune_with_linked_lists::<_, _, O>(self.kv_store.keys(), linked_list_mem, state_ptrs) + } } fn serialize( @@ -497,6 +548,93 @@ fn serialize( } } +fn serialize_with_linked_lists( + smt: &Smt, + key: Key, + cur_bits: Bits, + keys_to_include: &HashSet, + smt_mem: &mut Vec>, + linked_list_mem: &mut Vec>, + state_ptrs: &mut BTreeMap, +) -> usize { + if key.0.iter().all(F::is_zero) { + return 0; // `ptr=0` is an empty node. + } + + if !keys_to_include.contains(&cur_bits) || smt.db.get_node(&key).is_none() { + let index = smt_mem.len(); + smt_mem.push(Some(HASH_TYPE.into())); + smt_mem.push(Some(key2u(key))); + index + } else if let Some(node) = smt.db.get_node(&key) { + if node.0.iter().all(F::is_zero) { + panic!("wtf?"); + } + + if node.is_one_siblings() { + let val_h = node.0[4..8].try_into().unwrap(); + let val_a = smt.db.get_node(&Key(val_h)).unwrap().0[0..8] + .try_into() + .unwrap(); + let rem_key = Key(node.0[0..4].try_into().unwrap()); + let val = limbs2f(val_a); + let index = smt_mem.len(); + + // The last leaf must point to the new one. + let len = linked_list_mem.len(); + linked_list_mem[len - 1] = Some(U256::from(O + len)); + // The nibbles are the address. + linked_list_mem.push(Some(key2u(rem_key))); + // Set `value_ptr_ptr`. + linked_list_mem.push(Some(val)); + // Set the next node as the initial node. + linked_list_mem.push(Some(U256::from(O))); + + // Push the values in the smt memory + smt_mem.push(Some(LEAF_TYPE.into())); + smt_mem.push(Some(key2u(rem_key))); + smt_mem.push(Some(val)); + + // Put the pointer in state_ptrs + state_ptrs.insert(key2u(rem_key), O + len); + + index + } else { + let key_left = Key(node.0[0..4].try_into().unwrap()); + let key_right = Key(node.0[4..8].try_into().unwrap()); + let index = smt_mem.len(); + smt_mem.push(Some(INTERNAL_TYPE.into())); + smt_mem.push(Some(U256::zero())); + smt_mem.push(Some(U256::zero())); + let i_left = serialize_with_linked_lists::<_, O>( + smt, + key_left, + cur_bits.add_bit(false), + keys_to_include, + smt_mem, + linked_list_mem, + state_ptrs, + ) + .into(); + smt_mem[index + 1] = Some(i_left); + let i_right = serialize_with_linked_lists::<_, O>( + smt, + key_right, + cur_bits.add_bit(true), + keys_to_include, + smt_mem, + linked_list_mem, + state_ptrs, + ) + .into(); + smt_mem[index + 2] = Some(i_right); + index + } + } else { + unreachable!() + } +} + /// Hash a serialized state SMT, i.e., one where leaves hold accounts. pub fn hash_serialize(v: &[U256]) -> HashOut { _hash_serialize(v, 2) From 1b058c9287a69e8989d3992063f9b473d8c3f947 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 19 Sep 2024 14:51:04 +0200 Subject: [PATCH 02/60] [WIP] Adding preinitialization --- .../src/cpu/kernel/interpreter.rs | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 10af8d495..c6eb1e740 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -233,7 +233,7 @@ impl Interpreter { self.generation_state.inputs = inputs.trim(); // Initialize the MPT's pointers. - let (trie_root_ptrs, state_leaves, storage_leaves, trie_data) = + let (state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( &mut self.generation_state.accounts_pointers, &mut self.generation_state.storage_pointers, @@ -241,28 +241,15 @@ impl Interpreter { ) .expect("Invalid MPT data for preinitialization"); + let trie_root_ptrs = TrieRootPtrs { + state_root_ptr: None, + txn_root_ptr : load_transactions_mpt(&input.tries.transactions_trie, &mut trie_data), + receipt_root_ptr: load_receipts_mpt(&input.tries.transactions_trie, &mut trie_data), + }; + let trie_roots_after = &inputs.trie_roots_after; self.generation_state.trie_root_ptrs = trie_root_ptrs; - // Initialize the `TrieData` segment. - let preinit_trie_data_segment = MemorySegmentState { content: trie_data }; - let preinit_accounts_ll_segment = MemorySegmentState { - content: state_leaves, - }; - let preinit_storage_ll_segment = MemorySegmentState { - content: storage_leaves, - }; - self.insert_preinitialized_segment(Segment::TrieData, preinit_trie_data_segment); - self.insert_preinitialized_segment( - Segment::AccountsLinkedList, - preinit_accounts_ll_segment, - ); - self.insert_preinitialized_segment(Segment::StorageLinkedList, preinit_storage_ll_segment); - - // Initialize the accounts and storage BTrees. - self.generation_state.insert_all_slots_in_memory(); - self.generation_state.insert_all_accounts_in_memory(); - // Update the RLP and withdrawal prover inputs. let rlp_prover_inputs = all_rlp_prover_inputs_reversed(&inputs.signed_txns); let withdrawal_prover_inputs = all_withdrawals_prover_inputs_reversed(&inputs.withdrawals); From f7c49b5b8c57433f3f6a346110c5a49a5f15e842 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 25 Sep 2024 16:31:37 +0200 Subject: [PATCH 03/60] Fix syntactic errors on erc20 --- .../src/cpu/kernel/constants/mod.rs | 19 ++++++++++++++++ evm_arithmetization/src/generation/mod.rs | 5 ++++- evm_arithmetization/src/generation/mpt.rs | 22 +++++++++++++++++++ .../src/generation/trie_extractor.rs | 2 ++ evm_arithmetization/src/testing_utils.rs | 9 ++------ evm_arithmetization/src/util.rs | 2 +- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index c738bb582..764f760d6 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -446,10 +446,12 @@ pub mod cancun_constants { "BEACON_ROOTS_CONTRACT_STATE_KEY", *BEACON_ROOTS_CONTRACT_ADDRESS_HASHED.as_fixed_bytes(), ); + pub const BEACON_ROOTS_CONTRACT_CODE_LEN_U256: U256 = U256([0, 0, 0, 97]); pub const BEACON_ROOTS_CONTRACT_CODE: [u8; 97] = hex!("3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500"); pub const BEACON_ROOTS_CONTRACT_CODE_HASH: [u8; 32] = hex!("f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c"); + #[cfg(feature = "eth_mainnet")] pub const BEACON_ROOTS_ACCOUNT: AccountRlp = AccountRlp { nonce: U256::zero(), balance: U256::zero(), @@ -460,6 +462,14 @@ pub mod cancun_constants { code_hash: H256(BEACON_ROOTS_CONTRACT_CODE_HASH), }; + #[cfg(feature = "cdk_erigon")] + pub static BEACON_ROOTS_ACCOUNT: AccountRlp = AccountRlp { + nonce: U256::zero(), + balance: U256::zero(), + code_length: BEACON_ROOTS_CONTRACT_CODE_LEN_U256, + code_hash: H256(BEACON_ROOTS_CONTRACT_CODE_HASH), + }; + #[test] fn hashed() { assert_eq!( @@ -506,11 +516,13 @@ pub mod global_exit_root { pub const TIMESTAMP_STORAGE_POS: (&str, u64) = ("TIMESTAMP_STORAGE_POS", 2); pub const BLOCK_INFO_ROOT_STORAGE_POS: (&str, u64) = ("BLOCK_INFO_ROOT_STORAGE_POS", 3); + pub const GLOBAL_EXIT_ROOT_CONTRACT_CODE_LEN_U256: U256 = U256([0, 0, 0, 2112]); /// Taken from https://zkevm.polygonscan.com/address/0xa40D5f56745a118D0906a34E69aeC8C0Db1cB8fA#code. pub const GLOBAL_EXIT_ROOT_CONTRACT_CODE: [u8; 2112] = hex!("60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106ca565b610118565b61005b6100933660046106e5565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106ca565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103f1565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107e460279139610445565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb610519565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b83610541565b6040516001600160a01b038416907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a26000825111806103dc5750805b156101c3576103eb8383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a61035f565b604080516001600160a01b03928316815291841660208301520160405180910390a1610154816105e9565b6060833b6104a45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b0316856040516104bf9190610794565b600060405180830381855af49150503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b509150915061050f828286610675565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b803b6105a55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b03811661064e5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036105c8565b60608315610684575081610285565b8251156106945782518084602001fd5b8160405162461bcd60e51b815260040161032891906107b0565b80356001600160a01b03811681146106c557600080fd5b919050565b6000602082840312156106dc57600080fd5b610285826106ae565b6000806000604084860312156106fa57600080fd5b610703846106ae565b9250602084013567ffffffffffffffff8082111561072057600080fd5b818601915086601f83011261073457600080fd5b81358181111561074357600080fd5b87602082850101111561075557600080fd5b6020830194508093505050509250925092565b60005b8381101561078357818101518382015260200161076b565b838111156103eb5750506000910152565b600082516107a6818460208701610768565b9190910192915050565b60208152600082518060208401526107cf816040850160208701610768565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204675187caf3a43285d9a2c1844a981e977bd52a85ff073e7fc649f73847d70a464736f6c63430008090033"); pub const GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH: [u8; 32] = hex!("6bec2bf64f7e824109f6ed55f77dd7665801d6195e461666ad6a5342a9f6daf5"); + #[cfg(feature = "eth_mainnet")] pub const GLOBAL_EXIT_ROOT_ACCOUNT: AccountRlp = AccountRlp { nonce: U256::zero(), balance: U256::zero(), @@ -520,6 +532,13 @@ pub mod global_exit_root { )), code_hash: H256(GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH), }; + #[cfg(feature = "cdk_erigon")] + pub static GLOBAL_EXIT_ROOT_ACCOUNT: AccountRlp = AccountRlp { + nonce: U256::zero(), + balance: U256::zero(), + code_length: GLOBAL_EXIT_ROOT_CONTRACT_CODE_LEN_U256, + code_hash: H256(GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH), + }; #[test] fn hashed() { diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index bf4765683..7f6aec906 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -25,7 +25,9 @@ use crate::cpu::columns::CpuColumnsView; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::generation::state::{GenerationState, State}; -use crate::generation::trie_extractor::{get_receipt_trie, get_state_trie, get_txn_trie}; +#[cfg(feature = "eth_mainnet")] +use crate::generation::trie_extractor::get_state_trie; +use crate::generation::trie_extractor::{get_receipt_trie, get_txn_trie}; use crate::memory::segments::{Segment, PREINITIALIZED_SEGMENTS_INDICES}; use crate::proof::{ BlockHashes, BlockMetadata, ExtraBlockData, MemCap, PublicValues, RegistersData, TrieRoots, @@ -653,6 +655,7 @@ pub(crate) fn output_debug_tries(state: &GenerationState) -> an .read_global_metadata(GlobalMetadata::StateTrieRoot), ) .map_err(|_| anyhow!("State trie pointer is too large to fit in a usize."))?; + #[cfg(feature = "eth_mainnet")] log::debug!( "Computed state trie: {:?}", get_state_trie::(&state.memory, state_trie_ptr) diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index b182fa210..c032730c3 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -22,6 +22,7 @@ use crate::witness::errors::{ProgramError, ProverInputError}; use crate::Node; #[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[cfg(feature = "eth_mainnet")] pub struct AccountRlp { pub nonce: U256, pub balance: U256, @@ -29,6 +30,15 @@ pub struct AccountRlp { pub code_hash: H256, } +#[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[cfg(feature = "cdk_erigon")] +pub struct AccountRlp { + pub nonce: U256, + pub balance: U256, + pub code_length: U256, + pub code_hash: H256, +} + #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct TrieRootPtrs { pub state_root_ptr: Option, @@ -37,6 +47,7 @@ pub struct TrieRootPtrs { } impl Default for AccountRlp { + #[cfg(feature = "eth_mainnet")] fn default() -> Self { Self { nonce: U256::zero(), @@ -45,6 +56,15 @@ impl Default for AccountRlp { code_hash: keccak([]), } } + #[cfg(feature = "cdk_erigon")] + fn default() -> Self { + Self { + nonce: U256::zero(), + balance: U256::zero(), + code_length: U256::zero(), + code_hash: keccak([]), + } + } } #[derive(RlpEncodable, RlpDecodable, Debug, Clone)] @@ -222,6 +242,7 @@ where } } +#[cfg(feature = "eth_mainnet")] fn load_state_trie( trie: &HashedPartialTrie, key: Nibbles, @@ -330,6 +351,7 @@ fn load_state_trie( } } +#[cfg(feature = "eth_mainnet")] fn get_state_and_storage_leaves( trie: &HashedPartialTrie, key: Nibbles, diff --git a/evm_arithmetization/src/generation/trie_extractor.rs b/evm_arithmetization/src/generation/trie_extractor.rs index 48fc28f53..3af6cb6d9 100644 --- a/evm_arithmetization/src/generation/trie_extractor.rs +++ b/evm_arithmetization/src/generation/trie_extractor.rs @@ -89,6 +89,7 @@ pub(crate) fn read_logs( .collect() } +#[cfg(feature = "eth_mainnet")] pub(crate) fn read_state_rlp_value( memory: &MemoryState, slice: &MemoryValues, @@ -130,6 +131,7 @@ pub(crate) fn read_receipt_rlp_value( Ok(bytes) } +#[cfg(feature = "eth_mainnet")] pub(crate) fn get_state_trie( memory: &MemoryState, ptr: usize, diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index 7018e06be..39b149f82 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -72,6 +72,7 @@ pub fn update_beacon_roots_account_storage( } /// Returns the beacon roots contract account from its provided storage trie. +#[cfg(feature = "eth_mainnet")] pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { AccountRlp { storage_root: storage_trie.hash(), @@ -148,16 +149,10 @@ pub fn update_scalable_account_storage( insert_storage(storage_trie, slot.into_uint(), h2u(initial_trie_hash)) } +#[cfg(feature = "eth_mainnet")] pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { AccountRlp { storage_root: storage_trie.hash(), ..GLOBAL_EXIT_ROOT_ACCOUNT } } - -pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { - AccountRlp { - storage_root: storage_trie.hash(), - ..Default::default() - } -} diff --git a/evm_arithmetization/src/util.rs b/evm_arithmetization/src/util.rs index a9aae2d2b..93acb7e7e 100644 --- a/evm_arithmetization/src/util.rs +++ b/evm_arithmetization/src/util.rs @@ -210,7 +210,7 @@ pub(crate) fn biguint_to_mem_vec(x: BigUint) -> Vec { mem_vec } -pub(crate) fn h2u(h: H256) -> U256 { +pub fn h2u(h: H256) -> U256 { U256::from_big_endian(&h.0) } From e0e3ec82964e457d524cd3b918ef63547d8365ea Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 26 Sep 2024 14:29:07 +0200 Subject: [PATCH 04/60] [WIP] Add state linked list to the kernel --- .../src/cpu/kernel/aggregator.rs | 15 +- .../asm/mpt/linked_list/final_tries.asm | 234 ---- .../asm/mpt/linked_list/initial_tries.asm | 129 -- .../asm/mpt/linked_list/linked_list.asm | 1056 ----------------- .../src/cpu/kernel/constants/mod.rs | 4 +- 5 files changed, 14 insertions(+), 1424 deletions(-) delete mode 100644 evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/final_tries.asm delete mode 100644 evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/initial_tries.asm delete mode 100644 evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/linked_list.asm diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index caf0e29f1..0ef5993c0 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -10,7 +10,7 @@ use crate::cpu::kernel::constants::evm_constants; use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { - 157 + 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { 154 } else { @@ -120,6 +120,14 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/hash/sha2/temp_words.asm"), include_str!("asm/hash/sha2/write_length.asm"), include_str!("asm/main.asm"), + #[cfg(feature = "eth_mainnet")] + include_str!("asm/linked_list/accounts_linked_list.asm"), + #[cfg(feature = "eth_mainnet")] + include_str!("asm/linked_list/storage_linked_list.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/mpt/linked_list/state_linked_list.asm"), + include_str!("asm/linked_list/final_tries.asm"), + include_str!("asm/linked_list/initial_tries.asm"), include_str!("asm/memory/core.asm"), include_str!("asm/memory/memcpy.asm"), include_str!("asm/memory/memset.asm"), @@ -139,9 +147,6 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/mpt/insert/insert_extension.asm"), include_str!("asm/mpt/insert/insert_leaf.asm"), include_str!("asm/mpt/insert/insert_trie_specific.asm"), - include_str!("asm/mpt/linked_list/linked_list.asm"), - include_str!("asm/mpt/linked_list/final_tries.asm"), - include_str!("asm/mpt/linked_list/initial_tries.asm"), include_str!("asm/mpt/read.asm"), include_str!("asm/mpt/storage/storage_read.asm"), include_str!("asm/mpt/storage/storage_write.asm"), @@ -155,6 +160,8 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/rlp/read_to_memory.asm"), include_str!("asm/shift.asm"), include_str!("asm/signed.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/smt/utils.asm"), include_str!("asm/journal/journal.asm"), include_str!("asm/journal/account_loaded.asm"), include_str!("asm/journal/account_destroyed.asm"), 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 deleted file mode 100644 index 53093f4f4..000000000 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/final_tries.asm +++ /dev/null @@ -1,234 +0,0 @@ -// Given a pointer `root_ptr` to the root of a trie, insert all accounts in -// the accounts_linked_list starting at `account_ptr_ptr` as well as the -// respective storage slots in `storage_ptr_ptr`. -// Pre stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest -// Post stack: new_root_ptr. -global insert_all_accounts: - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - SWAP2 - DUP3 - MLOAD_GENERAL - // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - DUP1 - %eq_const(@U256_MAX) - %jumpi(no_more_accounts) - // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - DUP4 - %increment - MLOAD_GENERAL - // stack: account_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %add_const(2) - DUP1 - %mload_trie_data - // stack: storage_root_ptr, storage_root_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %stack - (storage_root_ptr, storage_root_ptr_ptr, key, storage_ptr_ptr) -> - (key, storage_ptr_ptr, storage_root_ptr, after_insert_all_slots, storage_root_ptr_ptr, key) - %jump(insert_all_slots) - -after_insert_all_slots: - // stack: storage_ptr_ptr', storage_root_ptr', storage_root_ptr_ptr, key, root_ptr, account_ptr_ptr, retdest - SWAP2 - %mstore_trie_data - // stack: storage_ptr_ptr', key, root_ptr, account_ptr_ptr, retdest - DUP4 - %increment - MLOAD_GENERAL - %stack - (payload_ptr, storage_ptr_ptr_p, key, root_ptr, account_ptr_ptr) -> - (root_ptr, 64, key, payload_ptr, after_insert_account, account_ptr_ptr, storage_ptr_ptr_p) - %jump(mpt_insert) -after_insert_account: - // stack: root_ptr', account_ptr_ptr, storage_ptr_ptr', retdest - SWAP1 - %next_account - // stack: account_ptr_ptr', root_ptr', storage_ptr_ptr', retdest - %jump(insert_all_accounts) - -no_more_accounts: - // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %stack (key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest) ->(retdest, root_ptr) - JUMP - -// Insert all slots before the account key changes -// Pre stack: addr, storage_ptr_ptr, root_ptr, retdest -// Post stack: storage_ptr_ptr', root_ptr' -global insert_all_slots: - DUP2 - MLOAD_GENERAL - DUP2 - EQ // Check that the node addres is the same as `addr` - %jumpi(insert_next_slot) - // The addr has changed, meaning that we've inserted all slots for addr - // stack: addr, storage_ptr_ptr, root_ptr, retdest - %stack (addr, storage_ptr_ptr, root_ptr, retdest) -> (retdest, storage_ptr_ptr, root_ptr) - JUMP - -insert_next_slot: - // stack: addr, storage_ptr_ptr, root_ptr, retdest - DUP2 - %increment - MLOAD_GENERAL - // stack: key, addr, storage_ptr_ptr, root_ptr, retdest - DUP3 - %add_const(2) - MLOAD_GENERAL - // stack: value, key, addr, storage_ptr_ptr, root_ptr, retdest - // If the value is 0, then payload_ptr = 0, and we don't need to insert a value in the `TrieData` segment. - DUP1 ISZERO %jumpi(insert_with_payload_ptr) - %get_trie_data_size // payload_ptr - SWAP1 %append_to_trie_data // append the value to the trie data segment -insert_with_payload_ptr: - %stack (payload_ptr, key, addr, storage_ptr_ptr, root_ptr) -> (root_ptr, 64, key, payload_ptr, after_insert_slot, storage_ptr_ptr, addr) - %jump(mpt_insert) -after_insert_slot: - // stack: root_ptr', storage_ptr_ptr, addr, retdest - SWAP1 - %next_slot - // stack: storage_ptr_ptr', root_ptr', addr - %stack (storage_ptr_ptr_p, root_ptr_p, addr) -> (addr, storage_ptr_ptr_p, root_ptr_p) - %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 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. -global delete_removed_accounts: - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - DUP1 - // 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 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 - %jumpi(delete_removed_accounts_end) - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - DUP1 - %next_account - %eq_const(@U256_MAX) // If the next node pointer is @U256_MAX, the node was deleted - %jumpi(delete_account) - // The account is still there so we need to delete any removed slot. - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - DUP1 - MLOAD_GENERAL - // stack: key, account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - DUP2 - %add_const(2) - MLOAD_GENERAL // get initial payload_ptr - %add_const(2) // storage_root_ptr_ptr = payload_ptr + 2 - %mload_trie_data - // stack: storage_root_ptr, key, account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - DUP3 - %increment - MLOAD_GENERAL // get dynamic payload_ptr - %add_const(2) // storage_root_ptr_ptr = dyn_payload_ptr + 2 - %stack - (storage_root_ptr_ptr, storage_root_ptr, key, account_ptr_ptr, root_ptr, storage_ptr_ptr) -> - (key, storage_root_ptr, storage_ptr_ptr, after_delete_removed_slots, storage_root_ptr_ptr, account_ptr_ptr, root_ptr) - %jump(delete_removed_slots) -after_delete_removed_slots: - // stack: storage_root_ptr', storage_ptr_ptr', storage_root_ptr_ptr, account_ptr_ptr, root_ptr, retdest - SWAP1 SWAP2 - // stack: storage_root_ptr_ptr, storage_root_ptr', storage_ptr_ptr', account_ptr_ptr, root_ptr, retdest - %mstore_trie_data - // stack: storage_ptr_ptr', account_ptr_ptr, root_ptr, retdest - SWAP1 - %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) // The next account in memory - // stack: account_ptr_ptr', storage_ptr_ptr', root_ptr, retdest - SWAP1 SWAP2 SWAP1 - %jump(delete_removed_accounts) - -delete_removed_accounts_end: - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - %stack (account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest) -> (retdest, root_ptr) - JUMP -delete_account: - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - DUP1 - MLOAD_GENERAL - %stack (key, account_ptr_ptr, root_ptr) -> (root_ptr, 64, key, after_mpt_delete, account_ptr_ptr) - // Pre stack: node_ptr, num_nibbles, key, retdest - // Post stack: updated_node_ptr - %jump(mpt_delete) -after_mpt_delete: - // stack: root_ptr', account_ptr_ptr, storage_ptr_ptr, retdest - SWAP1 - %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) - %jump(delete_removed_accounts) - -// Delete all slots in `storage_ptr_ptr` with address == `addr` and -// `storage_ptr_ptr` < `@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN`. -// Pre stack: addr, root_ptr, storage_ptr_ptr, retdest -// Post stack: new_root_ptr, storage_ptr_ptr'. -delete_removed_slots: - // stack: addr, root_ptr, storage_ptr_ptr, retdest - DUP3 - MLOAD_GENERAL - // stack: address, addr, root_ptr, storage_ptr_ptr, retdest - DUP2 - EQ - // stack: loaded_address == addr, addr, root_ptr, storage_ptr_ptr, retdest - %mload_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) - DUP5 - LT - MUL // AND - // stack: loaded_address == addr AND storage_ptr_ptr < GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN, addr, root_ptr, storage_ptr_ptr, retdest - // jump if we either change the address or reach the end of the initial linked list - %jumpi(maybe_delete_this_slot) - // If we are here we have deleted all the slots for this key - %stack (addr, root_ptr, storage_ptr_ptr, retdest) -> (retdest, root_ptr, storage_ptr_ptr) - JUMP -maybe_delete_this_slot: - // stack: addr, root_ptr, storage_ptr_ptr, retdest - DUP3 - %next_slot - %eq_const(@U256_MAX) // Check if the node was deleted - %jumpi(delete_this_slot) - // The slot was not deleted, so we skip it. - // stack: addr, root_ptr, storage_ptr_ptr, retdest - SWAP2 - %add_const(@STORAGE_LINKED_LISTS_NODE_SIZE) - SWAP2 - %jump(delete_removed_slots) -delete_this_slot: - // stack: addr, root_ptr, storage_ptr_ptr, retdest - DUP3 - %increment - MLOAD_GENERAL - %stack (key, addr, root_ptr, storage_ptr_ptr) -> (root_ptr, 64, key, after_mpt_delete_slot, addr, storage_ptr_ptr) - %jump(mpt_delete) -after_mpt_delete_slot: - // stack: root_ptr', addr, storage_ptr_ptr - SWAP2 - %add_const(@STORAGE_LINKED_LISTS_NODE_SIZE) - %stack (storage_ptr_ptr_p, addr, root_ptr_p) -> (addr, root_ptr_p, storage_ptr_ptr_p) - %jump(delete_removed_slots) - -global set_final_tries: - PUSH set_final_tries_after - %first_initial_slot // Skip the first node. - %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) - %first_initial_account // Skip the first node. - %jump(delete_removed_accounts) -set_final_tries_after: - // stack: new_state_root - PUSH set_final_tries_after_after SWAP1 - // stack: new_state_root, set_final_tries_after_after - %first_slot - SWAP1 - %first_account - %jump(insert_all_accounts) -set_final_tries_after_after: - //stack: new_state_root - %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) - JUMP - -%macro set_final_tries - // stack: (empty) - PUSH %%after - %jump(set_final_tries) -%%after: -%endmacro 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 deleted file mode 100644 index df4762a51..000000000 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/initial_tries.asm +++ /dev/null @@ -1,129 +0,0 @@ - -global set_initial_state_trie: - // stack: retdest - PUSH set_initial_state_trie_after - %first_initial_slot // Skip the first node. - %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) - %first_initial_account // Skip the first node. - %jump(insert_all_initial_accounts) -set_initial_state_trie_after: - //stack: new_state_root - %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) - JUMP - -%macro set_initial_state_trie - // stack: (empty) - PUSH %%after - %jump(set_initial_state_trie) -%%after: -%endmacro - -// Given a pointer `root_ptr` to the root of a trie, insert all the initial accounts in -// the accounts_linked_list starting at `account_ptr_ptr` as well as the -// respective initial storage slots in `storage_ptr_ptr`. -// Pre stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest -// Post stack: new_root_ptr. // The value of new_root_ptr shouldn't change -global insert_all_initial_accounts: - // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest - SWAP2 - DUP3 - MLOAD_GENERAL - // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - DUP4 - %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) - EQ - %jumpi(no_more_accounts) - // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - PUSH after_mpt_read - DUP2 - PUSH 64 - DUP6 - // stack: root_ptr, nibbles, key, after_mpt_read, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %jump(mpt_read) -after_mpt_read: - //stack: trie_account_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - DUP1 - %mload_trie_data - %add_const(2) - %mload_trie_data - // stack: trie_storage_root, trie_account_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - SWAP1 - // stack: trie_account_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - DUP6 - %add_const(2) // intial account_ptr = account_ptr_ptr + 2 - MLOAD_GENERAL - // stack: account_ptr, trie_account_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - DUP1 SWAP2 - // stack: trie_account_ptr_ptr, account_ptr, account_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %mstore_trie_data // The trie's account points to the linked list initial account - // stack: account_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %add_const(2) - // stack: storage_root_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - - %stack - (storage_root_ptr_ptr, trie_storage_root, key, storage_ptr_ptr) -> - (key, storage_ptr_ptr, trie_storage_root, after_insert_all_initial_slots, storage_root_ptr_ptr) - %jump(insert_all_initial_slots) - -after_insert_all_initial_slots: - // stack: storage_ptr_ptr', trie_storage_root_ptr', storage_root_ptr_ptr, root_ptr, account_ptr_ptr, retdest - SWAP2 - %mstore_trie_data - // stack: storage_ptr_ptr', root_ptr, account_ptr_ptr, retdest - SWAP2 - %next_initial_account - // stack: account_ptr_ptr', root_ptr, storage_ptr_ptr', retdest - %jump(insert_all_initial_accounts) - -no_more_accounts: - // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest - %stack (key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest) ->(retdest, root_ptr) - JUMP - -// Insert all slots before the account key changes -// Pre stack: addr, storage_ptr_ptr, root_ptr, retdest -// Post stack: storage_ptr_ptr', root_ptr' -global insert_all_initial_slots: - DUP2 - MLOAD_GENERAL - DUP2 - EQ // Check that the node address is the same as `addr` - DUP3 - %mload_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) - SUB - MUL - %jumpi(insert_next_slot) - // The addr has changed, meaning that we've inserted all slots for addr, - // or we reached the end of the initial storage linked list. - // stack: addr, storage_ptr_ptr, root_ptr, retdest - %stack (addr, storage_ptr_ptr, root_ptr, retdest) -> (retdest, storage_ptr_ptr, root_ptr) - JUMP -insert_next_slot: - // stack: addr, storage_ptr_ptr, root_ptr, retdest - DUP2 - %increment - MLOAD_GENERAL - // stack: key, addr, storage_ptr_ptr, root_ptr, retdest - DUP3 - %add_const(3) // inital value is at position 3 - MLOAD_GENERAL - // stack: value, key, addr, storage_ptr_ptr, root_ptr, retdest - // If the value is 0, then payload_ptr = 0, and we don't need to insert a value in the `TrieData` segment. - DUP1 ISZERO %jumpi(insert_with_payload_ptr) - %get_trie_data_size // payload_ptr - SWAP1 - %append_to_trie_data // append the value to the trie data segment -insert_with_payload_ptr: - %stack - (payload_ptr, key, addr, storage_ptr_ptr, root_ptr) -> - (root_ptr, 64, key, after_insert_slot, payload_ptr, storage_ptr_ptr, addr, root_ptr) - %jump(mpt_read) -after_insert_slot: - // stack: slot_ptr_ptr, payload_ptr, storage_ptr_ptr, addr, root_ptr, retdest - %mstore_trie_data - // stack: storage_ptr_ptr, addr, root_ptr, retdest - %next_initial_slot - // stack: storage_ptr_ptr', addr, root_ptr, retdest - SWAP1 - %jump(insert_all_initial_slots) - 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 deleted file mode 100644 index 650d69db2..000000000 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/linked_list/linked_list.asm +++ /dev/null @@ -1,1056 +0,0 @@ -/// Linked lists for accounts and storage slots. -/// The accounts linked list is stored in SEGMENT_ACCOUNTS_LINKED_LIST while the slots -/// are stored in SEGMENT_STORAGE_LINKED_LIST. The length of -/// the segments is stored in the associated global metadata. -/// Both arrays are stored in the kernel memory (context=0). -/// Searching and inserting is done by guessing the predecessor in the list. -/// If the address/storage key isn't found in the array, it is inserted -/// at the correct location. These linked lists are used to keep track of -/// inserted and deleted accounts/slots during the execution, so that the -/// initial and final MPT state tries can be reconstructed at the end of the execution. -/// An empty account linked list is written as -/// [@U256_MAX, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. -/// The linked list is preinitialized by appending accounts to the segment. Each account is encoded -/// using 4 values. -/// 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 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. -/// The linked list is preinitialized by appending storage slots to the segment. -/// Each slot is encoded using 5 values. -/// The values at the respective positions are: -/// - 0: The account key -/// - 1: The slot key -/// - 2: The slot value. -/// - 3: The initial slot value. -/// - 4: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. - -%macro store_initial_accounts - PUSH %%after - %jump(store_initial_accounts) -%%after: -%endmacro - -/// 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`. -/// It also checks that the next node address is current address + 4 -/// and that all keys are strictly increasing. -/// NOTE: It may be more efficient to check that the next node addres != U256_MAX -/// (i.e. node was not deleted) and ensure that no node with repeated key -/// is ever read. -global store_initial_accounts: - // stack: retdest - PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - ADD - // stack: cur_len, retdest - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - // stack: current_node_ptr, cur_len, retdest - DUP1 - MLOAD_GENERAL - // stack: current_addr_key, current_node_ptr, cur_len', retdest - %assert_eq_const(@U256_MAX) - DUP1 - %next_account - // stack: next_node_ptr, current_node_ptr, cur_len', retdest - DUP1 - SWAP2 - %next_initial_account - %assert_eq(store_initial_accounts_end) // next_node_ptr == current_node_ptr + node_size - // stack: next_node_ptr, cur_len', retdest - -loop_store_initial_accounts: - // stack: current_node_ptr, cur_len, retdest - %get_trie_data_size - // stack: cpy_ptr, current_node_ptr, cur_len, retdest - DUP2 - %increment - MLOAD_GENERAL - // 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, 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, cur_len, retdest - DUP1 - %mload_trie_data // storage_root_ptr - %append_to_trie_data - %increment - // 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, 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 - // Check next node ptr validity and strict keys monotonicity - DUP1 - MLOAD_GENERAL - // stack: current_addr_key, current_node_ptr, cur_len', retdest - SWAP1 - DUP1 - %next_account - // stack: next_node_ptr, current_node_ptr, current_addr_key, cur_len', retdest - DUP1 - SWAP2 - %next_initial_account - %assert_eq(store_initial_accounts_end_pop_key) // next_node_ptr == current_node_ptr + node_size - // stack: next_node_ptr, current_addr_key, cur_len', retdest - SWAP1 - DUP2 - MLOAD_GENERAL - %assert_gt // next_addr_key > current_addr_key - // stack: next_node_ptr, cur_len', retdest - %jump(loop_store_initial_accounts) - -store_initial_accounts_end_pop_key: - // stack: next_node_ptr, current_addr_key, cur_len', retdest - SWAP1 POP -store_initial_accounts_end: - // stack: next_node_ptr, cur_len', retdest - %assert_eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) - // stack: cur_len, retdest - DUP1 - %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) - %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) - JUMP - -%macro insert_account_with_overwrite - %stack (addr_key, ptr) -> (addr_key, ptr, %%after) - %jump(insert_account_with_overwrite) -%%after: -%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_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. -%macro get_valid_account_ptr - // stack: ptr/4 - // Check that the pointer is greater than the segment. - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - DUP2 - %mul_const(4) - // stack: ptr, @SEGMENT_ACCOUNTS_LINKED_LIST, ptr/4 - %increment %assert_gt - // stack: ptr/4 - DUP1 - PUSH 4 - %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 - // stack: @SEGMENT_ACCOUNTS_LINKED_LIST/4 + accounts_linked_list_len/4, ptr/4, ptr/4 - %assert_gt - %mul_const(4) -%endmacro - -global insert_account_with_overwrite: - // stack: addr_key, payload_ptr, retdest - PROVER_INPUT(linked_list::insert_account) - // stack: pred_ptr/4, addr_key, payload_ptr, retdest - %get_valid_account_ptr - // stack: pred_ptr, addr_key, payload_ptr, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, payload_ptr, retdest - DUP4 GT - DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // we need to insert a new node. - %jumpi(insert_new_account) - // stack: pred_addr_key, pred_ptr, addr_key, payload_ptr, retdest - // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - - // stack: pred_ptr, addr_key, payload_ptr, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, account_found_with_overwrite) - // The storage key is not in the list. - PANIC - -account_found_with_overwrite: - // The address was already in the list - // stack: pred_ptr, addr_key, payload_ptr, retdest - // Load the payload pointer - %increment - // stack: payload_ptr_ptr, addr_key, payload_ptr, retdest - DUP3 MSTORE_GENERAL - %pop2 - JUMP - -insert_new_account: - // stack: pred_addr_key, pred_ptr, addr_key, payload_ptr, retdest - POP - // 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_NEXT_AVAILABLE) - DUP2 - MLOAD_GENERAL - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest - // Check that this is not a deleted node - DUP1 - %eq_const(@U256_MAX) - %assert_zero - DUP1 - MLOAD_GENERAL - // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest - DUP5 - // Here, (addr_key > pred_addr_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). - // We should have (addr_key < next_addr_key), meaning the new value can be inserted between pred_ptr and next_ptr. - %assert_lt - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest - SWAP2 - DUP2 - // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, payload_ptr, retdest - MSTORE_GENERAL - // stack: new_ptr, next_ptr, addr_key, payload_ptr, retdest - DUP1 - DUP4 - MSTORE_GENERAL - // stack: new_ptr, next_ptr, addr_key, payload_ptr, retdest - %increment - DUP1 - DUP5 - MSTORE_GENERAL - // stack: new_ptr + 1, next_ptr, addr_key, payload_ptr, retdest - %increment - DUP1 - DUP5 - %clone_account - MSTORE_GENERAL - %increment - DUP1 - // stack: new_next_ptr, new_next_ptr, next_ptr, addr_key, payload_ptr, retdest - SWAP2 - MSTORE_GENERAL - // stack: new_next_ptr, addr_key, payload_ptr, retdest - %increment - %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 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::search_account) - // stack: pred_ptr/4, addr_key, retdest - %get_valid_account_ptr - // stack: pred_ptr, addr_key, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, retdest - DUP4 GT - DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // we need to insert a new node. - %jumpi(account_not_found) - // stack: pred_addr_key, pred_ptr, addr_key, retdest - // If we are here we know that addr_key <= pred_addr_key. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - - // stack: pred_ptr, addr_key, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, account_found) - // The storage key is not in the list. - PANIC - -account_found: - // The address was already in the list - // stack: pred_ptr, addr_key, retdest - // Load the payload pointer - %increment - MLOAD_GENERAL - // stack: orig_payload_ptr, addr_key, retdest - %stack (orig_payload_ptr, addr_key, retdest) -> (retdest, orig_payload_ptr) - JUMP - -account_not_found: - // stack: pred_addr_key, pred_ptr, addr_key, retdest - %stack (pred_addr_key, pred_ptr, addr_key, retdest) -> (retdest, 0) - JUMP - -%macro remove_account_from_linked_list - PUSH %%after - SWAP1 - %jump(remove_account) -%%after: -%endmacro - -/// Removes the address and its value from the access list. -/// Panics if the key is not in the list. -global remove_account: - // stack: addr_key, retdest - PROVER_INPUT(linked_list::remove_account) - // stack: pred_ptr/4, addr_key, retdest - %get_valid_account_ptr - // stack: pred_ptr, addr_key, retdest - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - // stack: next_ptr_ptr, addr_key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_ptr, next_ptr_ptr, addr_key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_addr_key, next_ptr, next_ptr_ptr, addr_key, retdest - DUP4 - %assert_eq - // stack: next_ptr, next_ptr_ptr, addr_key, retdest - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - // stack: next_next_ptr_ptr, next_ptr_ptr, addr_key, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, addr_key, retdest - SWAP1 - %mstore_u256_max - // stack: next_next_ptr, next_ptr_ptr, addr_key, retdest - MSTORE_GENERAL - POP - JUMP - - -// -// -// STORAGE linked list -// -// - -%macro store_initial_slots - PUSH %%after - %jump(store_initial_slots) -%%after: -%endmacro - - -/// 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`. -/// It also checks that the next node address is current address + 5 -/// and that all keys are strictly increasing. -/// NOTE: It may be more efficient to check that the next node addres != U256_MAX -/// (i.e. node was not deleted) and ensure that no node with repeated key -/// is ever read. -global store_initial_slots: - // stack: retdest - PUSH @STORAGE_LINKED_LISTS_NODE_SIZE - PUSH @SEGMENT_STORAGE_LINKED_LIST - ADD - // stack: cur_len, retdest - PUSH @SEGMENT_STORAGE_LINKED_LIST - DUP1 - MLOAD_GENERAL - // stack: current_addr_key, current_node_ptr, cur_len, retdest - %assert_eq_const(@U256_MAX) - - // stack: current_node_ptr, cur_len', retdest - DUP1 - %next_slot - // stack: next_node_ptr, current_node_ptr, cur_len, retdest - DUP1 - SWAP2 - %next_initial_slot - %assert_eq(store_initial_slots_end) // next_node_ptr == current_node_ptr + node_size - // stack: next_node_ptr, cur_len', retdest - -loop_store_initial_slots: - // stack: current_node_ptr, cur_len, retdest - DUP1 - %add_const(2) - MLOAD_GENERAL - // stack: value, current_node_ptr, cur_len, retdest - DUP2 - %add_const(@STORAGE_COPY_PAYLOAD_PTR) - // stack: cpy_value_ptr, value, current_node_ptr, cur_len, retdest - SWAP1 - MSTORE_GENERAL // Store cpy_value - // stack: current_node_ptr, cur_len, retdest - SWAP1 PUSH @STORAGE_LINKED_LISTS_NODE_SIZE - ADD - SWAP1 - // Check correctness of next node ptr and strict key monotonicity. - DUP1 - MLOAD_GENERAL - // stack: current_addr_key, current_node_ptr, cur_len', retdest - SWAP1 - DUP1 - %increment - MLOAD_GENERAL - // stack: current_slot_key, current_node_ptr, current_addr_key, cur_len', retdest - SWAP1 - DUP1 - %next_slot - // stack: next_node_ptr, current_node_ptr, current_slot_key, current_addr_key, cur_len', retdest - DUP1 - SWAP2 - %next_initial_slot - %assert_eq(store_initial_slots_end_pop_keys) // next_node_ptr == current_node_ptr + node_size - // stack: next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest - DUP1 - DUP1 - %increment - MLOAD_GENERAL - // stack: next_node_slot_key, next_node_ptr, next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest - SWAP1 - MLOAD_GENERAL - // stack: next_node_addr_key, next_node_slot_key, next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest - SWAP3 - LT - // stack: current_slot_key > next_node_slot_key, next_node_ptr, next_node_addr_key, current_addr_key, cur_len', retdest - SWAP2 - SWAP1 - SWAP3 - // stack: current_addr_key, next_node_addr_key, current_slot_key > next_node_slot_key, next_node_ptr, cur_len', retdest - DUP2 - DUP2 - EQ - // stack: current_addr_key == next_node_addr_key, current_addr_key, next_node_addr_key, current_slot_key > next_node_slot_key, next_node_ptr, cur_len', retdest - SWAP1 - SWAP3 - MUL // AND - // stack current_slot_key > next_node_slot_key AND current_addr_key == next_node_addr_key, next_node_addr_key, current_addr_key, next_node_ptr, cur_len', retdest - SWAP2 - LT - ADD // OR - %assert_nonzero - %jump(loop_store_initial_slots) - -store_initial_slots_end_pop_keys: - // stack: next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest - SWAP2 - %pop2 - -store_initial_slots_end: - // stack: next_node_ptr, cur_len', retdest - %assert_eq_const(@SEGMENT_STORAGE_LINKED_LIST) - - // stack: cur_len, retdest - DUP1 - %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) - %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) - JUMP - - -// Multiplies the value at the top of the stack, denoted by ptr/5, by 5 -// and aborts if ptr/5 >= (mem[@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE] - @SEGMENT_STORAGE_LINKED_LIST)/5. -// This way, @SEGMENT_STORAGE_LINKED_LIST + 5*ptr/5 must be pointing to the beginning of a node. -// TODO: Maybe we should check here if the node has been deleted. -%macro get_valid_slot_ptr - // stack: ptr/5 - DUP1 - PUSH 5 - PUSH @SEGMENT_STORAGE_LINKED_LIST - // stack: segment, 5, ptr/5, ptr/5 - %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 - DIV - // stack: accessed_strg_keys_len/5, ptr/5, ptr/5 - %assert_gt - %mul_const(5) - %add_const(@SEGMENT_STORAGE_LINKED_LIST) -%endmacro - -/// Inserts the pair (address_key, storage_key) and a new payload pointer into the linked list if it is not already present, -/// or modifies its payload if it was already present. -global insert_slot_with_value: - // stack: addr_key, key, value, retdest - PROVER_INPUT(linked_list::insert_slot) - // stack: pred_ptr/5, addr_key, key, value, retdest - %get_valid_slot_ptr - - // stack: pred_ptr, addr_key, key, value, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, value, retdest - DUP4 - GT - DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // we need to insert a new node. - %jumpi(insert_new_slot_with_value) - // stack: pred_addr_key, pred_ptr, addr_key, key, payload_ptr, retdest - // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - // stack: pred_ptr, addr_key, key, value, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: pred_key, pred_ptr, addr_key, key, value, retdest - DUP1 DUP5 - GT - %jumpi(insert_new_slot_with_value) - // stack: pred_key, pred_ptr, addr_key, key, value, retdest - DUP4 - // We know that key <= pred_key. It must hold that pred_key == key. - %assert_eq - - // stack: pred_ptr, addr_key, key, value, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@STORAGE_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, slot_found_write_value) - // The storage key is not in the list. - PANIC - -insert_new_slot_with_value: - // stack: pred_addr or pred_key, pred_ptr, addr_key, key, value, retdest - POP - // get the value of the next address - %add_const(@STORAGE_NEXT_NODE_PTR) - // stack: next_ptr_ptr, addr_key, key, value, retdest - %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) - DUP2 - MLOAD_GENERAL - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - // Check that this is not a deleted node - DUP1 - %eq_const(@U256_MAX) - %assert_zero - DUP1 - MLOAD_GENERAL - // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP1 - DUP6 - // Here, (addr_key > pred_addr_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). - // We should have (addr_key < next_addr_key), meaning the new value can be inserted between pred_ptr and next_ptr. - LT - %jumpi(next_node_ok_with_value) - // If addr_key <= next_addr_key, then it addr must be equal to next_addr - // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP5 - %assert_eq - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP1 // This is added just to have the correct stack in next_node_ok - DUP7 - // The next key must be strictly larger - %assert_lt - -next_node_ok_with_value: - // stack: next_addr or next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - POP - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - SWAP2 - DUP2 - // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, key, value, retdest - MSTORE_GENERAL - // stack: new_ptr, next_ptr, addr_key, key, value, retdest - // Write the address in the new node - DUP1 - DUP4 - MSTORE_GENERAL - // stack: new_ptr, next_ptr, addr_key, key, value, retdest - // Write the key in the new node - %increment - DUP1 - DUP5 - MSTORE_GENERAL - // stack: new_ptr + 1, next_ptr, addr_key, key, value, retdest - // Write the value in the linked list. - %increment - DUP1 %increment - // stack: new_ptr+3, new_value_ptr, next_ptr, addr_key, key, value, retdest - %stack (new_cloned_value_ptr, new_value_ptr, next_ptr, addr_key, key, value, retdest) - -> (value, new_cloned_value_ptr, value, new_value_ptr, new_cloned_value_ptr, next_ptr, retdest) - MSTORE_GENERAL // Store copied value. - MSTORE_GENERAL // Store value. - - // stack: new_ptr + 3, next_ptr, retdest - %increment - DUP1 - // stack: new_next_ptr_ptr, new_next_ptr_ptr, next_ptr, retdest - SWAP2 - MSTORE_GENERAL - // stack: new_next_ptr_ptr, retdest - %increment - %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) - // stack: retdest - JUMP - -slot_found_write_value: - // stack: pred_ptr, addr_key, key, value, retdest - %add_const(2) - %stack (payload_ptr, addr_key, key, value) -> (value, payload_ptr) - MSTORE_GENERAL - // stack: retdest - JUMP - -%macro insert_slot_with_value - // stack: addr, slot, value - %addr_to_state_key - SWAP1 - %slot_to_storage_key - %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 - // stack: addr_key, slot_key, value - %stack (addr_key, slot_key, value) -> (addr_key, slot_key, value, %%after) - %jump(insert_slot_with_value) -%%after: - // stack: (empty) -%endmacro - -/// Inserts the pair (address_key, storage_key) and payload pointer into the linked list if it is not already present, -/// or modifies its payload if it was already present. -/// Returns `value` if the storage key was inserted, `old_value` if it was already present. -global insert_slot: - // stack: addr_key, key, value, retdest - PROVER_INPUT(linked_list::insert_slot) - // stack: pred_ptr/5, addr_key, key, value, retdest - %get_valid_slot_ptr - - // stack: pred_ptr, addr_key, key, value, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, value, retdest - DUP4 - GT - DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // we need to insert a new node. - %jumpi(insert_new_slot) - // stack: pred_addr_key, pred_ptr, addr_key, key, value, retdest - // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - // stack: pred_ptr, addr_key, key, value, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: pred_key, pred_ptr, addr_key, key, value, retdest - DUP1 DUP5 - GT - %jumpi(insert_new_slot) - // stack: pred_key, pred_ptr, addr_key, key, value, retdest - DUP4 - // We know that key <= pred_key. It must hold that pred_key == key. - %assert_eq - // stack: pred_ptr, addr_key, key, value, retdest - - // stack: pred_ptr, addr_key, key, value, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@STORAGE_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, slot_found_write) - // The storage key is not in the list. - PANIC - -slot_found_write: - // The slot was already in the list - // stack: pred_ptr, addr_key, key, value, retdest - // Load the old value - %add_const(2) - DUP1 - MLOAD_GENERAL - // stack: old_value, pred_ptr + 2, addr_key, key, value, retdest - SWAP1 - DUP5 - MSTORE_GENERAL // Store the new value - %stack (old_value, addr_key, key, value, retdest) -> (retdest, old_value) - JUMP -insert_new_slot: - // stack: pred_addr or pred_key, pred_ptr, addr_key, key, value, retdest - POP - // 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_NEXT_AVAILABLE) - DUP2 - MLOAD_GENERAL - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - // Check that this is not a deleted node - DUP1 - %eq_const(@U256_MAX) - %assert_zero - DUP1 - MLOAD_GENERAL - // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP1 - DUP6 - // Here, (addr_key > pred_addr_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). - // We should have (addr_key < next_addr_key), meaning the new value can be inserted between pred_ptr and next_ptr. - LT - %jumpi(next_node_ok) - // If addr_key <= next_addr_key, then it addr must be equal to next_addr - // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP5 - %assert_eq - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - DUP1 // This is added just to have the correct stack in next_node_ok - DUP7 - // The next key must be strictly larger - %assert_lt -next_node_ok: - // stack: next_addr or next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - POP - // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest - SWAP2 - DUP2 - // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, key, value, retdest - MSTORE_GENERAL - // stack: new_ptr, next_ptr, addr_key, key, value, retdest - // Write the address in the new node - DUP1 - DUP4 - MSTORE_GENERAL - // stack: new_ptr, next_ptr, addr_key, key, value, retdest - // Write the key in the new node - %increment - DUP1 - DUP5 - MSTORE_GENERAL - // stack: new_ptr + 1, next_ptr, addr_key, key, value, retdest - // Store value - %increment - DUP1 - DUP6 - MSTORE_GENERAL - - // stack: new_ptr + 2, next_ptr, addr_key, key, value, retdest - // Store the copy of value - %increment - DUP1 - DUP6 - %clone_slot - MSTORE_GENERAL - // stack: new_ptr + 3, next_ptr, addr_key, key, value, retdest - %increment - DUP1 - // stack: new_next_ptr, new_next_ptr, next_ptr, addr_key, key, value, retdest - SWAP2 - MSTORE_GENERAL - // stack: new_next_ptr, addr_key, key, value, retdest - %increment - %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) - // stack: addr_key, key, value, retdest - %stack (addr_key, key, value, retdest) -> (retdest, value) - JUMP - -/// Searches the pair (address_key, storage_key) in the storage the linked list. -/// Returns `value` if the storage key was inserted, `old_value` if it was already present. -global search_slot: - // stack: addr_key, key, value, retdest - PROVER_INPUT(linked_list::search_slot) - // stack: pred_ptr/5, addr_key, key, value, retdest - %get_valid_slot_ptr - - // stack: pred_ptr, addr_key, key, value, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, value, retdest - DUP4 - GT - DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // the slot was not found - %jumpi(slot_not_found) - // stack: pred_addr_key, pred_ptr, addr_key, key, value, retdest - // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - // stack: pred_ptr, addr_key, key, value, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: pred_key, pred_ptr, addr_key, key, value, retdest - DUP1 DUP5 - GT - %jumpi(slot_not_found) - // stack: pred_key, pred_ptr, addr_key, key, value, retdest - DUP4 - // We know that key <= pred_key. It must hold that pred_key == key. - %assert_eq - // stack: pred_ptr, addr_key, key, value, retdest - - // stack: pred_ptr, addr_key, key, value, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@STORAGE_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, slot_found_no_write) - // The storage key is not in the list. - PANIC -slot_not_found: - // stack: pred_addr_or_pred_key, pred_ptr, addr_key, key, value, retdest - %stack (pred_addr_or_pred_key, pred_ptr, addr_key, key, value, retdest) - -> (retdest, value) - JUMP - -slot_found_no_write: - // The slot was already in the list - // stack: pred_ptr, addr_key, key, value, retdest - // Load the old value - %add_const(2) - MLOAD_GENERAL - // stack: old_value, addr_key, key, value, retdest - %stack (old_value, addr_key, key, value, retdest) -> (retdest, old_value) - JUMP - -%macro search_slot - // stack: state_key, storage_key, ptr - %stack (state_key, storage_key, ptr) -> (state_key, storage_key, ptr, %%after) - %jump(search_slot) -%%after: - // stack: value -%endmacro - -%macro remove_slot - %stack (key, addr_key) -> (addr_key, key, %%after) - %jump(remove_slot) -%%after: -%endmacro - -/// Removes the storage key and its value from the list. -/// Panics if the key is not in the list. -global remove_slot: - // stack: addr_key, key, retdest - PROVER_INPUT(linked_list::remove_slot) - // stack: pred_ptr/5, addr_key, key, retdest - %get_valid_slot_ptr - // stack: pred_ptr, addr_key, key, retdest - %add_const(@STORAGE_NEXT_NODE_PTR) - // stack: next_ptr_ptr, addr_key, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_ptr, next_ptr_ptr, addr_key, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_addr_key, next_ptr, next_ptr_ptr, addr_key, key, retdest - DUP4 - %assert_eq - // stack: next_ptr, next_ptr_ptr, addr_key, key, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: next_key, next_ptr, next_ptr_ptr, addr_key, key, retdest - DUP5 - %assert_eq - // stack: next_ptr, next_ptr_ptr, addr_key, key, retdest - %add_const(@STORAGE_NEXT_NODE_PTR) - // stack: next_next_ptr_ptr, next_ptr_ptr, addr_key, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, addr_key, key, retdest - // Mark the next node as deleted - SWAP1 - %mstore_u256_max - // stack: next_next_ptr, next_ptr_ptr, addr_key, key, retdest - MSTORE_GENERAL - %pop2 - JUMP - -/// Called when an account is deleted: it deletes all slots associated with the account. -global remove_all_account_slots: - // stack: addr_key, retdest - PROVER_INPUT(linked_list::remove_address_slots) - // pred_ptr/5, retdest - %get_valid_slot_ptr - // stack: pred_ptr, addr_key, retdest - // First, check that the previous address is not `addr` - DUP1 MLOAD_GENERAL - // stack: pred_addr_key, pred_ptr, addr_key, retdest - DUP3 EQ %jumpi(panic) - // stack: pred_ptr, addr_key, retdest - DUP1 - -// Now, while the next address is `addr`, remove the next slot. -remove_all_slots_loop: - // stack: pred_ptr, pred_ptr, addr_key, retdest - %add_const(@STORAGE_NEXT_NODE_PTR) DUP1 MLOAD_GENERAL - // stack: cur_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest - DUP1 %eq_const(@U256_MAX) %jumpi(remove_all_slots_end) - DUP1 %add_const(@STORAGE_NEXT_NODE_PTR) MLOAD_GENERAL - // stack: next_ptr, cur_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest - SWAP1 DUP1 - // stack: cur_ptr, cur_ptr, next_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest - MLOAD_GENERAL - DUP6 EQ ISZERO %jumpi(remove_all_slots_pop_and_end) - - // Remove slot: update the value in cur_ptr_ptr, and set cur_ptr+4 to @U256_MAX. - // stack: cur_ptr, next_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest - SWAP2 SWAP1 - // stack: next_ptr, cur_ptr_ptr, cur_ptr, pred_ptr, addr_key, retdest - MSTORE_GENERAL - // stack: cur_ptr, pred_ptr, addr_key, retdest - %add_const(@STORAGE_NEXT_NODE_PTR) - %mstore_u256_max - // stack: pred_ptr, addr_key, retdest - DUP1 - %jump(remove_all_slots_loop) - -remove_all_slots_pop_and_end: - POP -remove_all_slots_end: - // stack: next_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest - %pop4 JUMP - -%macro remove_all_account_slots - %stack (addr_key) -> (addr_key, %%after) - %jump(remove_all_account_slots) -%%after: -%endmacro - -%macro read_accounts_linked_list - %stack (addr) -> (addr, %%after) - %addr_to_state_key - %jump(search_account) -%%after: - // stack: account_ptr -%endmacro - -%macro read_storage_linked_list - // stack: slot - %slot_to_storage_key - %stack (storage_key) -> (storage_key, 0, %%after) - %address - %addr_to_state_key - // stack: addr_key, storage_key, 0, %%after - %jump(search_slot) -%%after: - // stack: slot_value -%endmacro - -%macro read_storage_linked_list_w_addr - // stack: slot, address - %slot_to_storage_key - %stack (storage_key, address) -> (address, storage_key, 0, %%after) - %addr_to_state_key - // stack: addr_key, storage_key, 0, %%after - %jump(search_slot) -%%after: - // stack: slot_value -%endmacro - -%macro read_storage_linked_list_w_state_key - // stack: slot, state_key - %slot_to_storage_key - %stack (storage_key, state_key) -> (state_key, storage_key, 0, %%after) - %jump(search_slot) -%%after: - // stack: slot_ptr -%endmacro - -%macro first_account - // stack: empty - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - %next_account -%endmacro - -%macro first_initial_account - // stack: empty - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - %next_initial_account -%endmacro - -%macro next_account - // stack: node_ptr - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - MLOAD_GENERAL - // stack: next_node_ptr -%endmacro - -%macro next_initial_account - // stack: node_ptr - %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) - // stack: next_node_ptr -%endmacro - -%macro first_slot - // stack: empty - PUSH @SEGMENT_STORAGE_LINKED_LIST - %next_slot -%endmacro - -%macro first_initial_slot - // stack: empty - PUSH @SEGMENT_STORAGE_LINKED_LIST - %next_initial_slot -%endmacro - -%macro next_slot - // stack: node_ptr - %add_const(@STORAGE_NEXT_NODE_PTR) - MLOAD_GENERAL - // stack: next_node_ptr -%endmacro - -%macro next_initial_slot - // stack: node_ptr - %add_const(@STORAGE_LINKED_LISTS_NODE_SIZE) - // stack: next_node_ptr -%endmacro - -%macro next_hash_node - // stack: hash_node_ptr - %add_const(4) - // stack: next_hash_node_ptr -%endmacro - -// Skip over the the first three words (number of nibbles and keys) -// and load the hash from memory. -%macro get_hash - // stack: hash_node_ptr - %add_const(3) - // stack: next_ptr - MLOAD_GENERAL - // stack: hash -%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 764f760d6..27322bec5 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -391,12 +391,14 @@ const MAX_RLP_PREFIX_SIZE: (&str, u8) = ("MAX_RLP_PREFIX_SIZE", 9); pub(crate) const INITIAL_RLP_ADDR: (&str, usize) = ("INITIAL_RLP_ADDR", Segment::RlpRaw as usize + 1); -const LINKED_LISTS_CONSTANTS: [(&str, u16); 5] = [ +const LINKED_LISTS_CONSTANTS: [(&str, u16); 7] = [ ("ACCOUNTS_LINKED_LISTS_NODE_SIZE", 4), ("STORAGE_LINKED_LISTS_NODE_SIZE", 5), + ("STATE_LINKED_LISTS_NODE_SIZE", 4), ("ACCOUNTS_NEXT_NODE_PTR", 3), ("STORAGE_NEXT_NODE_PTR", 4), ("STORAGE_COPY_PAYLOAD_PTR", 3), + ("STATE_COPY_PAYLOAD_PTR", 4), ]; /// Cancun-related constants From 46309d4c4ff7217014f7330f98f24311d53c562c Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 26 Sep 2024 18:03:40 +0200 Subject: [PATCH 05/60] Update state accesses --- .../src/cpu/kernel/aggregator.rs | 4 +- .../src/cpu/kernel/asm/beacon_roots.asm | 48 ++++++++++++------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index 0ef5993c0..e20fd6332 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 154 + 155 } else { // unreachable 0 @@ -125,7 +125,7 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ #[cfg(feature = "eth_mainnet")] include_str!("asm/linked_list/storage_linked_list.asm"), #[cfg(feature = "cdk_erigon")] - include_str!("asm/mpt/linked_list/state_linked_list.asm"), + include_str!("asm/linked_list/state_linked_list.asm"), include_str!("asm/linked_list/final_tries.asm"), include_str!("asm/linked_list/initial_tries.asm"), include_str!("asm/memory/core.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm index 265d61b90..831112679 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm @@ -15,36 +15,48 @@ global set_beacon_root: // stack: timestamp, 8191, timestamp, retdest MOD // stack: timestamp_idx, timestamp, retdest - %slot_to_storage_key - // stack: timestamp_slot_key, timestamp, retdest PUSH @BEACON_ROOTS_CONTRACT_STATE_KEY %parent_beacon_block_root - // stack: calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: calldata, state_key, timestamp_idx, timestamp, retdest PUSH @HISTORY_BUFFER_LENGTH - DUP5 - MOD - // stack: timestamp_idx, calldata, state_key, timestamp_slot_key, timestamp, retdest + DUP4 + // stack: timestamp_idx, calldata, state_key, timestamp_idx, timestamp, retdest %add_const(@HISTORY_BUFFER_LENGTH) - // stack: root_idx, calldata, state_key, timestamp_slot_key, timestamp, retdest - %slot_to_storage_key - // stack: root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: root_idx, calldata, state_key, timestamp_idx, timestamp, retdest DUP3 - // stack: state_key, root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: state_key, root_slot_idx, calldata, state_key, timestamp_idx, timestamp, retdest DUP3 ISZERO %jumpi(delete_root_idx_slot) - // stack: state_key, root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest - %insert_slot_with_value_from_keys - // stack: state_key, timestamp_slot_key, timestamp, retdest - %insert_slot_with_value_from_keys + // stack: state_key, root_slot_idx, calldata, state_key, timestamp_idx, timestamp, retdest + %insert_beacon_slot + // stack: state_key, timestamp_idx, timestamp, retdest + %insert_beacon_slot // stack: retdest JUMP +%macro insert_beacon_slot + #[cfg(feature = "eth_mainnet")] + { + // stack: state_key, slot, calldata + SWAP1 + %slot_to_storage_key + SWAP1 + %insert_slot_with_value_from_keys + } + { + %key_storage + %beacon_slot_to_key + + } +%endmacro + delete_root_idx_slot: - // stack: state_key, root_slot_key, 0, state_key, timestamp_slot_key, timestamp, retdest - DUP3 DUP3 DUP3 + // stack: state_key, root_slot_idx, 0, state_key, timestamp_idx, timestamp, retdest + DUP2 DUP2 %search_slot - // stack: slot_exists, state_key, root_slot_key, 0, state_key, timestamp_slot_key, timestamp, retdest + // stack: slot_exists, state_key, root_slot_idx, 0, state_key, timestamp_idx, timestamp, retdest +// -----> Aca voy %jumpi(remove_root_idx_slot) - // stack: state_key, root_slot_key, 0, state_key, timestamp_slot_key, timestamp, retdest + // stack: state_key, root_slot_key, 0, state_key, timestamp_idx, timestamp, retdest %pop3 // stack: state_key, timestamp_slot_key, timestamp, retdest %insert_slot_with_value_from_keys From 23f4b1780a0861498cd92968fddfda280935e9c7 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Mon, 30 Sep 2024 14:52:02 +0200 Subject: [PATCH 06/60] Unify storage API + add type2 storage API --- .../src/cpu/kernel/asm/beacon_roots.asm | 37 +++++-------------- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 16 +++----- .../cpu/kernel/asm/journal/storage_change.asm | 5 ++- .../kernel/asm/mpt/storage/storage_read.asm | 3 +- .../kernel/asm/mpt/storage/storage_write.asm | 9 ++--- .../asm/transactions/common_decoding.asm | 7 ++-- 6 files changed, 29 insertions(+), 48 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm index 831112679..ef07cfe28 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm @@ -27,47 +27,30 @@ global set_beacon_root: // stack: state_key, root_slot_idx, calldata, state_key, timestamp_idx, timestamp, retdest DUP3 ISZERO %jumpi(delete_root_idx_slot) // stack: state_key, root_slot_idx, calldata, state_key, timestamp_idx, timestamp, retdest - %insert_beacon_slot + %insert_slot_from_addr_key // stack: state_key, timestamp_idx, timestamp, retdest - %insert_beacon_slot + %insert_slot_from_addr_key // stack: retdest JUMP -%macro insert_beacon_slot - #[cfg(feature = "eth_mainnet")] - { - // stack: state_key, slot, calldata - SWAP1 - %slot_to_storage_key - SWAP1 - %insert_slot_with_value_from_keys - } - { - %key_storage - %beacon_slot_to_key - - } -%endmacro - delete_root_idx_slot: // stack: state_key, root_slot_idx, 0, state_key, timestamp_idx, timestamp, retdest DUP2 DUP2 - %search_slot + %search_slot_from_addr_key // stack: slot_exists, state_key, root_slot_idx, 0, state_key, timestamp_idx, timestamp, retdest -// -----> Aca voy %jumpi(remove_root_idx_slot) // stack: state_key, root_slot_key, 0, state_key, timestamp_idx, timestamp, retdest %pop3 - // stack: state_key, timestamp_slot_key, timestamp, retdest - %insert_slot_with_value_from_keys + // stack: state_key, timestamp_idx, timestamp, retdest + %insert_slot_from_addr_key // stack: retdest JUMP remove_root_idx_slot: - // stack: state_key, root_slot_key, 0, state_key, timestamp_slot_key, timestamp, retdest - %stack(state_key, storage_key, zero) -> (storage_key, state_key) - %remove_slot - // stack: state_key, timestamp_slot_key, timestamp, retdest - %insert_slot_with_value_from_keys + // stack: state_key, root_slot_idx, 0, state_key, timestamp_slot_idx, timestamp, retdest + %remove_slot_from_addr_key + POP + // stack: state_key, timestamp_slot_idx, timestamp, retdest + %insert_slot_from_addr_key // stack: retdest JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index fa8828097..2aea67b22 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -21,9 +21,9 @@ global update_scalable_block_number: // stack: retdest // Check timestamp - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY PUSH @TIMESTAMP_STORAGE_POS - %read_storage_linked_list_w_state_key + PUSH @ADDRESS_SCALABLE_L2_STATE_KEY + %read_slot_from_addr_key // stack: old_timestamp, retdest %timestamp GT %jumpi(update_scalable_timestamp) @@ -74,11 +74,9 @@ global update_scalable_l1blockhash: // stack: addr, len, l1blockhash, retdest KECCAK_GENERAL // stack: slot, l1blockhash, retdest - %slot_to_storage_key - // stack: storage_key, l1blockhash, retdest PUSH @GLOBAL_EXIT_ROOT_MANAGER_L2_STATE_KEY - // stack: state_key, storage_key, l1blockhash, retdest - %insert_slot_with_value_from_keys + // stack: state_key, slot, l1blockhash, retdest + %insert_slot_from_addr_key // stack: retdest JUMP @@ -112,10 +110,8 @@ global create_scalable_l2_account: %macro write_scalable_storage // stack: slot, value - %slot_to_storage_key - // stack: storage_key, value PUSH @ADDRESS_SCALABLE_L2_STATE_KEY - // stack: state_key, storage_key, value - %insert_slot_with_value_from_keys + // stack: state_key, slot, value + %insert_slot_from_addr_key // stack: (empty) %endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm index 695975c1f..0b1cb0972 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm @@ -11,7 +11,7 @@ global revert_storage_change: // stack: address, slot, prev_value, retdest DUP3 ISZERO %jumpi(delete) // stack: address, slot, prev_value, retdest - %insert_slot_with_value + %insert_slot JUMP delete: @@ -21,4 +21,5 @@ delete: %slot_to_storage_key SWAP1 %addr_to_state_key // stack: addr_key, slot_key, retdest - %jump(remove_slot) + %remove_slot_from_addr_key + JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_read.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_read.asm index 882a85973..5cdb18a69 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_read.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_read.asm @@ -5,7 +5,8 @@ %endmacro global sload_current: - %read_storage_linked_list + // stack: slot, retdest + %read_slot_from_current_addr // stack: value, retdest SWAP1 JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm index 589c44094..d7b81d0f7 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -114,7 +114,7 @@ sstore_after_refund: // stack: slot, value, kexit_info %address - %insert_slot_with_value + %insert_slot EXIT_KERNEL @@ -129,8 +129,7 @@ sstore_delete: %address %addr_to_state_key // stack: addr_key, slot, value, kexit_info - SWAP2 POP - // stack: slot, addr_key, kexit_info - %slot_to_storage_key - %remove_slot + %remove_slot_from_addr_key + // stack: value, kexit_info + POP EXIT_KERNEL 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 6ee92ca2b..41848c4cc 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm @@ -198,6 +198,7 @@ sk_loop: DUP2 DUP2 EQ %jumpi(end_sk) // stack: rlp_addr, sk_end_rlp_addr, addr, end_rlp_addr %decode_rlp_scalar // Storage key // TODO: Should panic when key is not 32 bytes? +global debug_todo_is_this_a_key_or_a_slot: %stack (rlp_addr, key, sk_end_rlp_addr, addr, end_rlp_addr) -> (addr, key, sk_loop_contd, rlp_addr, sk_end_rlp_addr, addr, end_rlp_addr) %jump(insert_accessed_storage_keys_with_original_value) @@ -225,10 +226,10 @@ decode_and_store_access_list_finish: %endmacro insert_accessed_storage_keys_with_original_value: - %stack (addr, key, retdest) -> (key, addr, after_read, addr, key, retdest) + %stack (addr, key, retdest) -> (addr, key, after_read, addr, key, retdest) %jump(sload_with_addr) after_read: - %stack (value, addr, key, retdest) -> ( addr, key, value, retdest) + %stack (value, addr, key, retdest) -> (addr, key, value, retdest) %insert_accessed_storage_keys // stack: cold_access, value_ptr, value, retdest SWAP2 @@ -239,7 +240,7 @@ after_read: JUMP sload_with_addr: - %read_storage_linked_list_w_addr + %read_slot_from_addr // stack: value, retdest SWAP1 JUMP From b096342c7702a3136ffebc93c70aed3e4097eb89 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Mon, 30 Sep 2024 15:01:44 +0200 Subject: [PATCH 07/60] Missing files --- .../asm/linked_list/accounts_linked_list.asm | 412 +++++++++++++++ .../kernel/asm/linked_list/final_tries.asm | 234 +++++++++ .../kernel/asm/linked_list/initial_tries.asm | 129 +++++ .../asm/linked_list/state_linked_list.asm | 405 +++++++++++++++ .../asm/linked_list/storage_linked_list.asm | 486 ++++++++++++++++++ .../src/cpu/kernel/asm/smt/delete.asm | 293 +++++++++++ .../src/cpu/kernel/asm/smt/hash.asm | 85 +++ .../src/cpu/kernel/asm/smt/insert.asm | 175 +++++++ .../src/cpu/kernel/asm/smt/keys.asm | 131 +++++ .../src/cpu/kernel/asm/smt/read.asm | 110 ++++ .../src/cpu/kernel/asm/smt/utils.asm | 129 +++++ evm_arithmetization/tests/erc20_type2.rs | 318 ++++++++++++ 12 files changed, 2907 insertions(+) create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/smt/insert.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/smt/keys.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/smt/read.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/smt/utils.asm create mode 100644 evm_arithmetization/tests/erc20_type2.rs diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm new file mode 100644 index 000000000..d5e89f18a --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm @@ -0,0 +1,412 @@ +/// The accounts linked list is stored in SEGMENT_ACCOUNTS_LINKED_LIST in the kernel memory (context=0). +/// The length of the segment is stored in @GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE. +/// Searching and inserting is done by guessing the predecessor in the list. +/// If the address key isn't found in the array, it is inserted +/// at the correct location. The linked lists are used to keep track of +/// inserted, modified and deleted accounts during the execution, so that the +/// initial and final MPT state tries can be reconstructed at the end of the execution. +/// An empty account linked list is written as +/// [@U256_MAX, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. +/// Each account is encoded using 4 values: +/// - 0: The account key +/// - 1: A ptr to the payload (the account values) +/// - 2: A ptr to the initial payload. +/// - 3: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. + +%macro store_initial_accounts + PUSH %%after + %jump(store_initial_accounts) +%%after: +%endmacro + +/// 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`. +/// It also checks that the next node address is current address + 4 +/// and that all keys are strictly increasing. +/// NOTE: It may be more efficient to check that the next node addres != U256_MAX +/// (i.e. node was not deleted) and ensure that no node with repeated key +/// is ever read. +global store_initial_accounts: + // stack: retdest + PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + ADD + // stack: cur_len, retdest + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + // stack: current_node_ptr, cur_len, retdest + DUP1 + MLOAD_GENERAL + // stack: current_addr_key, current_node_ptr, cur_len', retdest + %assert_eq_const(@U256_MAX) + DUP1 + %next_account + // stack: next_node_ptr, current_node_ptr, cur_len', retdest + DUP1 + SWAP2 + %next_initial_account + %assert_eq(store_initial_accounts_end) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, cur_len', retdest + +loop_store_initial_accounts: + // stack: current_node_ptr, cur_len, retdest + %get_trie_data_size + // stack: cpy_ptr, current_node_ptr, cur_len, retdest + DUP2 + %increment + MLOAD_GENERAL + // 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, 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, cur_len, retdest + DUP1 + %mload_trie_data // storage_root_ptr + %append_to_trie_data + %increment + // 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, 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 + // Check next node ptr validity and strict keys monotonicity + DUP1 + MLOAD_GENERAL + // stack: current_addr_key, current_node_ptr, cur_len', retdest + SWAP1 + DUP1 + %next_account + // stack: next_node_ptr, current_node_ptr, current_addr_key, cur_len', retdest + DUP1 + SWAP2 + %next_initial_account + %assert_eq(store_initial_accounts_end_pop_key) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, current_addr_key, cur_len', retdest + SWAP1 + DUP2 + MLOAD_GENERAL + %assert_gt // next_addr_key > current_addr_key + // stack: next_node_ptr, cur_len', retdest + %jump(loop_store_initial_accounts) + +store_initial_accounts_end_pop_key: + // stack: next_node_ptr, current_addr_key, cur_len', retdest + SWAP1 POP +store_initial_accounts_end: + // stack: next_node_ptr, cur_len', retdest + %assert_eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + // stack: cur_len, retdest + DUP1 + %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + JUMP + +%macro insert_account_with_overwrite + %stack (addr_key, ptr) -> (addr_key, ptr, %%after) + %jump(insert_account_with_overwrite) +%%after: +%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_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. +%macro get_valid_account_ptr + // stack: ptr/4 + // Check that the pointer is greater than the segment. + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + DUP2 + %mul_const(4) + // stack: ptr, @SEGMENT_ACCOUNTS_LINKED_LIST, ptr/4 + %increment %assert_gt + // stack: ptr/4 + DUP1 + PUSH 4 + %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 + // stack: @SEGMENT_ACCOUNTS_LINKED_LIST/4 + accounts_linked_list_len/4, ptr/4, ptr/4 + %assert_gt + %mul_const(4) +%endmacro + +global insert_account_with_overwrite: + // stack: addr_key, payload_ptr, retdest + PROVER_INPUT(linked_list::insert_account) + // stack: pred_ptr/4, addr_key, payload_ptr, retdest + %get_valid_account_ptr + // stack: pred_ptr, addr_key, payload_ptr, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, payload_ptr, retdest + DUP4 GT + DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // we need to insert a new node. + %jumpi(insert_new_account) + // stack: pred_addr_key, pred_ptr, addr_key, payload_ptr, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + + // stack: pred_ptr, addr_key, payload_ptr, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, account_found_with_overwrite) + // The storage key is not in the list. + PANIC + +account_found_with_overwrite: + // The address was already in the list + // stack: pred_ptr, addr_key, payload_ptr, retdest + // Load the payload pointer + %increment + // stack: payload_ptr_ptr, addr_key, payload_ptr, retdest + DUP3 MSTORE_GENERAL + %pop2 + JUMP + +insert_new_account: + // stack: pred_addr_key, pred_ptr, addr_key, payload_ptr, retdest + POP + // 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_NEXT_AVAILABLE) + DUP2 + MLOAD_GENERAL + // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest + // Check that this is not a deleted node + DUP1 + %eq_const(@U256_MAX) + %assert_zero + DUP1 + MLOAD_GENERAL + // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest + DUP5 + // Here, (addr_key > pred_addr_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). + // We should have (addr_key < next_addr_key), meaning the new value can be inserted between pred_ptr and next_ptr. + %assert_lt + // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, payload_ptr, retdest + SWAP2 + DUP2 + // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, payload_ptr, retdest + MSTORE_GENERAL + // stack: new_ptr, next_ptr, addr_key, payload_ptr, retdest + DUP1 + DUP4 + MSTORE_GENERAL + // stack: new_ptr, next_ptr, addr_key, payload_ptr, retdest + %increment + DUP1 + DUP5 + MSTORE_GENERAL + // stack: new_ptr + 1, next_ptr, addr_key, payload_ptr, retdest + %increment + DUP1 + DUP5 + %clone_account + MSTORE_GENERAL + %increment + DUP1 + // stack: new_next_ptr, new_next_ptr, next_ptr, addr_key, payload_ptr, retdest + SWAP2 + MSTORE_GENERAL + // stack: new_next_ptr, addr_key, payload_ptr, retdest + %increment + %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 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::search_account) + // stack: pred_ptr/4, addr_key, retdest + %get_valid_account_ptr + // stack: pred_ptr, addr_key, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, retdest + DUP4 GT + DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // we need to insert a new node. + %jumpi(account_not_found) + // stack: pred_addr_key, pred_ptr, addr_key, retdest + // If we are here we know that addr_key <= pred_addr_key. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + + // stack: pred_ptr, addr_key, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, account_found) + // The storage key is not in the list. + PANIC + +account_found: + // The address was already in the list + // stack: pred_ptr, addr_key, retdest + // Load the payload pointer + %increment + MLOAD_GENERAL + // stack: orig_payload_ptr, addr_key, retdest + %stack (orig_payload_ptr, addr_key, retdest) -> (retdest, orig_payload_ptr) + JUMP + +account_not_found: + // stack: pred_addr_key, pred_ptr, addr_key, retdest + %stack (pred_addr_key, pred_ptr, addr_key, retdest) -> (retdest, 0) + JUMP + +%macro remove_account_from_linked_list + PUSH %%after + SWAP1 + %jump(remove_account) +%%after: +%endmacro + +/// Removes the address and its value from the access list. +/// Panics if the key is not in the list. +global remove_account: + // stack: addr_key, retdest + PROVER_INPUT(linked_list::remove_account) + // stack: pred_ptr/4, addr_key, retdest + %get_valid_account_ptr + // stack: pred_ptr, addr_key, retdest + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + // stack: next_ptr_ptr, addr_key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_ptr, next_ptr_ptr, addr_key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_addr_key, next_ptr, next_ptr_ptr, addr_key, retdest + DUP4 + %assert_eq + // stack: next_ptr, next_ptr_ptr, addr_key, retdest + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + // stack: next_next_ptr_ptr, next_ptr_ptr, addr_key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, addr_key, retdest + SWAP1 + %mstore_u256_max + // stack: next_next_ptr, next_ptr_ptr, addr_key, retdest + MSTORE_GENERAL + POP + JUMP + +/// Called when an account is deleted: it deletes all slots associated with the account. +global remove_all_account_slots: + // stack: addr_key, retdest + PROVER_INPUT(linked_list::remove_address_slots) + // pred_ptr/5, retdest + %get_valid_slot_ptr + // stack: pred_ptr, addr_key, retdest + // First, check that the previous address is not `addr` + DUP1 MLOAD_GENERAL + // stack: pred_addr_key, pred_ptr, addr_key, retdest + DUP3 EQ %jumpi(panic) + // stack: pred_ptr, addr_key, retdest + DUP1 + +// Now, while the next address is `addr`, remove the next slot. +remove_all_slots_loop: + // stack: pred_ptr, pred_ptr, addr_key, retdest + %add_const(@STORAGE_NEXT_NODE_PTR) DUP1 MLOAD_GENERAL + // stack: cur_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest + DUP1 %eq_const(@U256_MAX) %jumpi(remove_all_slots_end) + DUP1 %add_const(@STORAGE_NEXT_NODE_PTR) MLOAD_GENERAL + // stack: next_ptr, cur_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest + SWAP1 DUP1 + // stack: cur_ptr, cur_ptr, next_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest + MLOAD_GENERAL + DUP6 EQ ISZERO %jumpi(remove_all_slots_pop_and_end) + + // Remove slot: update the value in cur_ptr_ptr, and set cur_ptr+4 to @U256_MAX. + // stack: cur_ptr, next_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest + SWAP2 SWAP1 + // stack: next_ptr, cur_ptr_ptr, cur_ptr, pred_ptr, addr_key, retdest + MSTORE_GENERAL + // stack: cur_ptr, pred_ptr, addr_key, retdest + %add_const(@STORAGE_NEXT_NODE_PTR) + %mstore_u256_max + // stack: pred_ptr, addr_key, retdest + DUP1 + %jump(remove_all_slots_loop) + +remove_all_slots_pop_and_end: + POP +remove_all_slots_end: + // stack: next_ptr, cur_ptr_ptr, pred_ptr, addr_key, retdest + %pop4 JUMP + +%macro remove_all_account_slots + %stack (addr_key) -> (addr_key, %%after) + %jump(remove_all_account_slots) +%%after: +%endmacro + +%macro read_accounts_linked_list + %stack (addr) -> (addr, %%after) + %addr_to_state_key + %jump(search_account) +%%after: + // stack: account_ptr +%endmacro + +%macro first_account + // stack: empty + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + %next_account +%endmacro + +%macro first_initial_account + // stack: empty + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + %next_initial_account +%endmacro + +%macro next_account + // stack: node_ptr + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + // stack: next_node_ptr +%endmacro + +%macro next_initial_account + // stack: node_ptr + %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) + // stack: next_node_ptr +%endmacro \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm new file mode 100644 index 000000000..53093f4f4 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm @@ -0,0 +1,234 @@ +// Given a pointer `root_ptr` to the root of a trie, insert all accounts in +// the accounts_linked_list starting at `account_ptr_ptr` as well as the +// respective storage slots in `storage_ptr_ptr`. +// Pre stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest +// Post stack: new_root_ptr. +global insert_all_accounts: + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + SWAP2 + DUP3 + MLOAD_GENERAL + // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + DUP1 + %eq_const(@U256_MAX) + %jumpi(no_more_accounts) + // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + DUP4 + %increment + MLOAD_GENERAL + // stack: account_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %add_const(2) + DUP1 + %mload_trie_data + // stack: storage_root_ptr, storage_root_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %stack + (storage_root_ptr, storage_root_ptr_ptr, key, storage_ptr_ptr) -> + (key, storage_ptr_ptr, storage_root_ptr, after_insert_all_slots, storage_root_ptr_ptr, key) + %jump(insert_all_slots) + +after_insert_all_slots: + // stack: storage_ptr_ptr', storage_root_ptr', storage_root_ptr_ptr, key, root_ptr, account_ptr_ptr, retdest + SWAP2 + %mstore_trie_data + // stack: storage_ptr_ptr', key, root_ptr, account_ptr_ptr, retdest + DUP4 + %increment + MLOAD_GENERAL + %stack + (payload_ptr, storage_ptr_ptr_p, key, root_ptr, account_ptr_ptr) -> + (root_ptr, 64, key, payload_ptr, after_insert_account, account_ptr_ptr, storage_ptr_ptr_p) + %jump(mpt_insert) +after_insert_account: + // stack: root_ptr', account_ptr_ptr, storage_ptr_ptr', retdest + SWAP1 + %next_account + // stack: account_ptr_ptr', root_ptr', storage_ptr_ptr', retdest + %jump(insert_all_accounts) + +no_more_accounts: + // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %stack (key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest) ->(retdest, root_ptr) + JUMP + +// Insert all slots before the account key changes +// Pre stack: addr, storage_ptr_ptr, root_ptr, retdest +// Post stack: storage_ptr_ptr', root_ptr' +global insert_all_slots: + DUP2 + MLOAD_GENERAL + DUP2 + EQ // Check that the node addres is the same as `addr` + %jumpi(insert_next_slot) + // The addr has changed, meaning that we've inserted all slots for addr + // stack: addr, storage_ptr_ptr, root_ptr, retdest + %stack (addr, storage_ptr_ptr, root_ptr, retdest) -> (retdest, storage_ptr_ptr, root_ptr) + JUMP + +insert_next_slot: + // stack: addr, storage_ptr_ptr, root_ptr, retdest + DUP2 + %increment + MLOAD_GENERAL + // stack: key, addr, storage_ptr_ptr, root_ptr, retdest + DUP3 + %add_const(2) + MLOAD_GENERAL + // stack: value, key, addr, storage_ptr_ptr, root_ptr, retdest + // If the value is 0, then payload_ptr = 0, and we don't need to insert a value in the `TrieData` segment. + DUP1 ISZERO %jumpi(insert_with_payload_ptr) + %get_trie_data_size // payload_ptr + SWAP1 %append_to_trie_data // append the value to the trie data segment +insert_with_payload_ptr: + %stack (payload_ptr, key, addr, storage_ptr_ptr, root_ptr) -> (root_ptr, 64, key, payload_ptr, after_insert_slot, storage_ptr_ptr, addr) + %jump(mpt_insert) +after_insert_slot: + // stack: root_ptr', storage_ptr_ptr, addr, retdest + SWAP1 + %next_slot + // stack: storage_ptr_ptr', root_ptr', addr + %stack (storage_ptr_ptr_p, root_ptr_p, addr) -> (addr, storage_ptr_ptr_p, root_ptr_p) + %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 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. +global delete_removed_accounts: + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + DUP1 + // 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 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 + %jumpi(delete_removed_accounts_end) + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + DUP1 + %next_account + %eq_const(@U256_MAX) // If the next node pointer is @U256_MAX, the node was deleted + %jumpi(delete_account) + // The account is still there so we need to delete any removed slot. + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + DUP1 + MLOAD_GENERAL + // stack: key, account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + DUP2 + %add_const(2) + MLOAD_GENERAL // get initial payload_ptr + %add_const(2) // storage_root_ptr_ptr = payload_ptr + 2 + %mload_trie_data + // stack: storage_root_ptr, key, account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + DUP3 + %increment + MLOAD_GENERAL // get dynamic payload_ptr + %add_const(2) // storage_root_ptr_ptr = dyn_payload_ptr + 2 + %stack + (storage_root_ptr_ptr, storage_root_ptr, key, account_ptr_ptr, root_ptr, storage_ptr_ptr) -> + (key, storage_root_ptr, storage_ptr_ptr, after_delete_removed_slots, storage_root_ptr_ptr, account_ptr_ptr, root_ptr) + %jump(delete_removed_slots) +after_delete_removed_slots: + // stack: storage_root_ptr', storage_ptr_ptr', storage_root_ptr_ptr, account_ptr_ptr, root_ptr, retdest + SWAP1 SWAP2 + // stack: storage_root_ptr_ptr, storage_root_ptr', storage_ptr_ptr', account_ptr_ptr, root_ptr, retdest + %mstore_trie_data + // stack: storage_ptr_ptr', account_ptr_ptr, root_ptr, retdest + SWAP1 + %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) // The next account in memory + // stack: account_ptr_ptr', storage_ptr_ptr', root_ptr, retdest + SWAP1 SWAP2 SWAP1 + %jump(delete_removed_accounts) + +delete_removed_accounts_end: + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + %stack (account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest) -> (retdest, root_ptr) + JUMP +delete_account: + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + DUP1 + MLOAD_GENERAL + %stack (key, account_ptr_ptr, root_ptr) -> (root_ptr, 64, key, after_mpt_delete, account_ptr_ptr) + // Pre stack: node_ptr, num_nibbles, key, retdest + // Post stack: updated_node_ptr + %jump(mpt_delete) +after_mpt_delete: + // stack: root_ptr', account_ptr_ptr, storage_ptr_ptr, retdest + SWAP1 + %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) + %jump(delete_removed_accounts) + +// Delete all slots in `storage_ptr_ptr` with address == `addr` and +// `storage_ptr_ptr` < `@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN`. +// Pre stack: addr, root_ptr, storage_ptr_ptr, retdest +// Post stack: new_root_ptr, storage_ptr_ptr'. +delete_removed_slots: + // stack: addr, root_ptr, storage_ptr_ptr, retdest + DUP3 + MLOAD_GENERAL + // stack: address, addr, root_ptr, storage_ptr_ptr, retdest + DUP2 + EQ + // stack: loaded_address == addr, addr, root_ptr, storage_ptr_ptr, retdest + %mload_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) + DUP5 + LT + MUL // AND + // stack: loaded_address == addr AND storage_ptr_ptr < GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN, addr, root_ptr, storage_ptr_ptr, retdest + // jump if we either change the address or reach the end of the initial linked list + %jumpi(maybe_delete_this_slot) + // If we are here we have deleted all the slots for this key + %stack (addr, root_ptr, storage_ptr_ptr, retdest) -> (retdest, root_ptr, storage_ptr_ptr) + JUMP +maybe_delete_this_slot: + // stack: addr, root_ptr, storage_ptr_ptr, retdest + DUP3 + %next_slot + %eq_const(@U256_MAX) // Check if the node was deleted + %jumpi(delete_this_slot) + // The slot was not deleted, so we skip it. + // stack: addr, root_ptr, storage_ptr_ptr, retdest + SWAP2 + %add_const(@STORAGE_LINKED_LISTS_NODE_SIZE) + SWAP2 + %jump(delete_removed_slots) +delete_this_slot: + // stack: addr, root_ptr, storage_ptr_ptr, retdest + DUP3 + %increment + MLOAD_GENERAL + %stack (key, addr, root_ptr, storage_ptr_ptr) -> (root_ptr, 64, key, after_mpt_delete_slot, addr, storage_ptr_ptr) + %jump(mpt_delete) +after_mpt_delete_slot: + // stack: root_ptr', addr, storage_ptr_ptr + SWAP2 + %add_const(@STORAGE_LINKED_LISTS_NODE_SIZE) + %stack (storage_ptr_ptr_p, addr, root_ptr_p) -> (addr, root_ptr_p, storage_ptr_ptr_p) + %jump(delete_removed_slots) + +global set_final_tries: + PUSH set_final_tries_after + %first_initial_slot // Skip the first node. + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + %first_initial_account // Skip the first node. + %jump(delete_removed_accounts) +set_final_tries_after: + // stack: new_state_root + PUSH set_final_tries_after_after SWAP1 + // stack: new_state_root, set_final_tries_after_after + %first_slot + SWAP1 + %first_account + %jump(insert_all_accounts) +set_final_tries_after_after: + //stack: new_state_root + %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + JUMP + +%macro set_final_tries + // stack: (empty) + PUSH %%after + %jump(set_final_tries) +%%after: +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm new file mode 100644 index 000000000..df4762a51 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm @@ -0,0 +1,129 @@ + +global set_initial_state_trie: + // stack: retdest + PUSH set_initial_state_trie_after + %first_initial_slot // Skip the first node. + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + %first_initial_account // Skip the first node. + %jump(insert_all_initial_accounts) +set_initial_state_trie_after: + //stack: new_state_root + %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + JUMP + +%macro set_initial_state_trie + // stack: (empty) + PUSH %%after + %jump(set_initial_state_trie) +%%after: +%endmacro + +// Given a pointer `root_ptr` to the root of a trie, insert all the initial accounts in +// the accounts_linked_list starting at `account_ptr_ptr` as well as the +// respective initial storage slots in `storage_ptr_ptr`. +// Pre stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest +// Post stack: new_root_ptr. // The value of new_root_ptr shouldn't change +global insert_all_initial_accounts: + // stack: account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest + SWAP2 + DUP3 + MLOAD_GENERAL + // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + DUP4 + %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) + EQ + %jumpi(no_more_accounts) + // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + PUSH after_mpt_read + DUP2 + PUSH 64 + DUP6 + // stack: root_ptr, nibbles, key, after_mpt_read, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %jump(mpt_read) +after_mpt_read: + //stack: trie_account_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + DUP1 + %mload_trie_data + %add_const(2) + %mload_trie_data + // stack: trie_storage_root, trie_account_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + SWAP1 + // stack: trie_account_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + DUP6 + %add_const(2) // intial account_ptr = account_ptr_ptr + 2 + MLOAD_GENERAL + // stack: account_ptr, trie_account_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + DUP1 SWAP2 + // stack: trie_account_ptr_ptr, account_ptr, account_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %mstore_trie_data // The trie's account points to the linked list initial account + // stack: account_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %add_const(2) + // stack: storage_root_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + + %stack + (storage_root_ptr_ptr, trie_storage_root, key, storage_ptr_ptr) -> + (key, storage_ptr_ptr, trie_storage_root, after_insert_all_initial_slots, storage_root_ptr_ptr) + %jump(insert_all_initial_slots) + +after_insert_all_initial_slots: + // stack: storage_ptr_ptr', trie_storage_root_ptr', storage_root_ptr_ptr, root_ptr, account_ptr_ptr, retdest + SWAP2 + %mstore_trie_data + // stack: storage_ptr_ptr', root_ptr, account_ptr_ptr, retdest + SWAP2 + %next_initial_account + // stack: account_ptr_ptr', root_ptr, storage_ptr_ptr', retdest + %jump(insert_all_initial_accounts) + +no_more_accounts: + // stack: key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest + %stack (key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest) ->(retdest, root_ptr) + JUMP + +// Insert all slots before the account key changes +// Pre stack: addr, storage_ptr_ptr, root_ptr, retdest +// Post stack: storage_ptr_ptr', root_ptr' +global insert_all_initial_slots: + DUP2 + MLOAD_GENERAL + DUP2 + EQ // Check that the node address is the same as `addr` + DUP3 + %mload_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) + SUB + MUL + %jumpi(insert_next_slot) + // The addr has changed, meaning that we've inserted all slots for addr, + // or we reached the end of the initial storage linked list. + // stack: addr, storage_ptr_ptr, root_ptr, retdest + %stack (addr, storage_ptr_ptr, root_ptr, retdest) -> (retdest, storage_ptr_ptr, root_ptr) + JUMP +insert_next_slot: + // stack: addr, storage_ptr_ptr, root_ptr, retdest + DUP2 + %increment + MLOAD_GENERAL + // stack: key, addr, storage_ptr_ptr, root_ptr, retdest + DUP3 + %add_const(3) // inital value is at position 3 + MLOAD_GENERAL + // stack: value, key, addr, storage_ptr_ptr, root_ptr, retdest + // If the value is 0, then payload_ptr = 0, and we don't need to insert a value in the `TrieData` segment. + DUP1 ISZERO %jumpi(insert_with_payload_ptr) + %get_trie_data_size // payload_ptr + SWAP1 + %append_to_trie_data // append the value to the trie data segment +insert_with_payload_ptr: + %stack + (payload_ptr, key, addr, storage_ptr_ptr, root_ptr) -> + (root_ptr, 64, key, after_insert_slot, payload_ptr, storage_ptr_ptr, addr, root_ptr) + %jump(mpt_read) +after_insert_slot: + // stack: slot_ptr_ptr, payload_ptr, storage_ptr_ptr, addr, root_ptr, retdest + %mstore_trie_data + // stack: storage_ptr_ptr, addr, root_ptr, retdest + %next_initial_slot + // stack: storage_ptr_ptr', addr, root_ptr, retdest + SWAP1 + %jump(insert_all_initial_slots) + diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm new file mode 100644 index 000000000..7d7301275 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm @@ -0,0 +1,405 @@ +/// The state linked list is stored in SEGMENT_ACCOUNTS_LINKED_LIST in the kernel memory (context=0). +/// The length of the segment is stored in @GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE. +/// Searching and inserting is done by guessing the predecessor in the list. +/// If the key isn't found in the array, it is inserted +/// at the correct location. The linked list is used to keep track of +/// inserted, modified and deleted accounts balances, nonces, storage, etc, during the execution, so that the +/// initial and final MPT state tries can be reconstructed at the end of the execution. +/// An empty astate linked list is written as +/// [@U256_MAX, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. +/// Each node is encoded using 4 values: +/// - 0: The key +/// - 1: The value +/// - 2: The initial value. +/// - 3: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. + +%macro store_initial_state + PUSH %%after + %jump(store_initial_state) +%%after: +%endmacro + + +/// Iterates over the initial state linked list and copies the values in the inital values slot. +/// Computes the length of `SEGMENT_STORAGE_LINKED_LIST` and +/// checks against `GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE`. +/// It also checks that the next node address is current address + 5 +/// and that all keys are strictly increasing. +/// NOTE: It may be more efficient to check that the next node addres != U256_MAX +/// (i.e. node was not deleted) and ensure that no node with repeated key +/// is ever read. +global store_initial_state: + // stack: retdest + PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE + PUSH @ACCOUNTS_STORAGE_LINKED_LIST + ADD + // stack: cur_len, retdest + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + DUP1 + MLOAD_GENERAL + // stack: current_key, current_node_ptr, cur_len, retdest + %assert_eq_const(@U256_MAX) + + // stack: current_node_ptr, cur_len', retdest + DUP1 + %next_node + // stack: next_node_ptr, current_node_ptr, cur_len, retdest + DUP1 + SWAP2 + %next_initial_node + %assert_eq(store_initial_state_end) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, cur_len', retdest + +loop_store_initial_state: + // stack: current_node_ptr, cur_len, retdest + DUP1 + %increment + MLOAD_GENERAL + // stack: value, current_node_ptr, cur_len, retdest + DUP2 + %add_const(@STATE_COPY_PAYLOAD_PTR) + // stack: cpy_value_ptr, value, current_node_ptr, cur_len, retdest + SWAP1 + MSTORE_GENERAL // Store cpy_value + // stack: current_node_ptr, cur_len, retdest + SWAP1 PUSH @STATE_LINKED_LISTS_NODE_SIZE + ADD + SWAP1 + // Check correctness of next node ptr and strict key monotonicity. + DUP1 + MLOAD_GENERAL + // stack: current_key, current_node_ptr, cur_len', retdest + SWAP1 + DUP1 + %next_node + // stack: next_node_ptr, current_node_ptr, current_key, cur_len', retdest + DUP1 + SWAP2 + %next_initial_node + %assert_eq(store_initial_state_end_pop_key) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, current_key, cur_len', retdest + SWAP1 + DUP2 + MLOAD_GENERAL + %assert_gt // next_key > current_key + // stack: next_node_ptr, cur_len', retdest + %jump(loop_store_initial_accounts) + +store_initial_state_end_pop_key: + // stack: next_node_ptr, current_key, cur_len', retdest + SWAP1 POP + +store_state_slots_end: + // stack: next_node_ptr, cur_len', retdest + %assert_eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + + // stack: cur_len, retdest + DUP1 + %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + JUMP + + +// 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_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. +%macro get_valid_state_ptr + // stack: ptr/4 + // Check that the pointer is greater than the segment. + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + DUP2 + %mul_const(4) + // stack: ptr, @SEGMENT_ACCOUNTS_LINKED_LIST, ptr/4 + %increment %assert_gt + // stack: ptr/4 + DUP1 + PUSH 4 + %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 + // stack: @SEGMENT_ACCOUNTS_LINKED_LIST/4 + accounts_linked_list_len/4, ptr/4, ptr/4 + %assert_gt + %mul_const(4) +%endmacro + +%macro insert_slot + // stack: addr, slot, value + %addr_to_state_key + %key_storage + %insert_key +%%after: + // stack: (empty) +%endmacro + +%macro insert_slot_from_addr_key + // stack: addr_key, slot_key, value + %key_storage + %insert_key +%%after: + // stack: (empty) +%endmacro + + +%macro insert_key + %stack (key, value) -> (key, value, %%after) + %jump(insert_key) + %%after: +%endmacro + +/// Inserts the pair `(key, value)` into the linked list if `key` was not already present, +/// or modifies the vealue if it was already present. +global insert_key: + // stack: key, value, retdest + PROVER_INPUT(linked_list::insert_state) + // stack: pred_ptr/4, key, value, retdest + %get_valid_state_ptr + + // stack: pred_ptr, key, value, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_key, pred_key, pred_ptr, key, value, retdest + DUP4 + GT + DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // we need to insert a new node. + %jumpi(insert_new_key) + // stack: pred_key, pred_ptr, key, value, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + // stack: pred_ptr, key, value, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, key_found_with_overwrite) + // The key is not in the list. + PANIC + +key_found_with_overwrite: + // The key was already in the list + // stack: pred_ptr, key, value, retdest + // Load the payload pointer + %increment + // stack: payload_ptr_ptr, key, value, retdest + DUP3 MSTORE_GENERAL + %pop2 + JUMP + +insert_new_key: + // stack: pred_key, pred_ptr, key, value, retdest + POP + // get the value of the next address + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + // stack: next_ptr_ptr, key, value, retdest + %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + DUP2 + MLOAD_GENERAL + // stack: next_ptr, new_ptr, next_ptr_ptr, key, value, retdest + // Check that this is not a deleted node + DUP1 + %eq_const(@U256_MAX) + %assert_zero + DUP1 + MLOAD_GENERAL + // stack: next_key, next_ptr, new_ptr, next_ptr_ptr, key, value, retdest + DUP5 + // Here, (key > pred_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). + // We should have (key < next_key), meaning the new value can be inserted between pred_ptr and next_ptr. + %assert_lt + // stack: next_ptr, new_ptr, next_ptr_ptr, key, value, retdest + SWAP2 + DUP2 + // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, key, value, retdest + MSTORE_GENERAL + // stack: new_ptr, next_ptr, key, value, retdest + DUP1 + DUP4 + MSTORE_GENERAL + // stack: new_ptr, next_ptr, key, value, retdest + %increment + DUP1 + DUP5 + MSTORE_GENERAL + // stack: new_ptr + 1, next_ptr, key, value, retdest + %add_const(2) // TODO: We're skiping the initial value. This shuould also done with the accounts bc this value should't be used. + DUP1 + // stack: new_next_ptr, new_next_ptr, next_ptr, key, value, retdest + SWAP2 + MSTORE_GENERAL + // stack: new_next_ptr, key, value, retdest + %increment + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + // stack: key, value, retdest + %pop2 + JUMP + + +/// Searches the key in the state the linked list. If the key is stored +/// returns the current value of the key, or 0 otherwise. +global search_key: + // stack: key, retdest + PROVER_INPUT(linked_list::search_state) + // stack: pred_ptr/4, key, retdest + %get_valid_state_ptr + + // stack: pred_ptr, key, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_key, pred_key, pred_ptr, key, retdest + DUP4 + GT + DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // the key was not found. + %jumpi(key_not_found) + // stack: pred_addr_key, pred_ptr, addr_key, key, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + // stack: pred_ptr, key, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@STATE_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, key_found) + // The key is not in the list. + PANIC + +key_found: + // The key was already in the list. + // stack: pred_ptr, key, retdest + %increment + MLOAD_GENERAL + // stack: value, key, retdest + %stack (value, key, retdest) -> (retdest, value) + JUMP + +key_not_found: + // stack: pred_key, pred_ptr, key, retdest + %stack (pred_key, pred_ptr, key, retdest) -> (retdest, 0) + JUMP + +%macro search_key + // stack: state_key, storage_key, ptr + %stack (key, ptr) -> (key, ptr, %%after) + %jump(search_key) +%%after: + // stack: value +%endmacro + +%macro search_slot_from_addr_key + // stack: addr_key, slot + %key_storage + %search_key +%endmacro + +%macro remove_key + PUSH %%after + SWAP1 + %jump(remove_key) +%%after: +%endmacro + +%macro remove_slot_from_addr_key + %key_storage + %remove_key +%endmacro + +/// Removes the key and its value from the state linked list. +/// Panics if the key is not in the list. +global remove_key: + // stack: key, retdest + PROVER_INPUT(linked_list::remove_slot) + // stack: pred_ptr/4, key, retdest + %get_valid_state_ptr + // stack: pred_ptr, key, retdest + %add_const(@STATE_NEXT_NODE_PTR) + // stack: next_ptr_ptr, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_ptr, next_ptr_ptr, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_key, next_ptr, next_ptr_ptr, key, retdest + DUP4 + %assert_eq + // stack: next_ptr, next_ptr_ptr, key, retdest + %add_const(@STATE_NEXT_NODE_PTR) + // stack: next_next_ptr_ptr, next_ptr_ptr, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, key, retdest + SWAP1 + %mstore_u256_max + // stack: next_next_ptr, next_ptr_ptr, key, retdest + MSTORE_GENERAL + POP + JUMP + +%macro read_slot_from_current_addr + // stack: slot + %address + %addr_to_state_key + %key_storage + %stack (storage_key) -> (storage_key, %%after) + // stack: storage_key, %%after + %jump(search_key) +%%after: + // stack: slot_value +%endmacro + +%macro read_slot_from_addr_key + // stack: state_key, slot + %slot_to_storage_key + %stack (storage_key) -> (storage_key, %%after) + %jump(search_key) +%%after: + // stack: slot_value +%endmacro + +%macro read_slot_from_addr + // stack: address, slot + %addr_to_state_key + %key_storage + %stack (storage_key_found) -> (storage_key, %%after) + // stack: storage_key, %%after + %jump(search_key) +%%after: + // stack: slot_value +%endmacro + +%macro first_node + // stack: empty + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + %next_slot +%endmacro + +%macro first_initial_node + // stack: empty + PUSH @SEGMENT_ACCONTS_LINKED_LIST + %next_initial_node +%endmacro + +%macro next_node + // stack: node_ptr + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + // stack: next_node_ptr +%endmacro + +%macro next_initial_node + // stack: node_ptr + %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) + // stack: next_node_ptr +%endmacro \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm new file mode 100644 index 000000000..840081382 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm @@ -0,0 +1,486 @@ +/// The storage linked list is stored in SEGMENT_STORAGE_LINKED_LIST in the kernel memory (context=0). +/// The length of the segment is stored in GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE. +/// Searching and inserting is done by guessing the predecessor in the list. +/// If the storage key isn't found in the array, it is inserted +/// at the correct location. This linked list is used to keep track of +/// inserted and deleted slots during the execution, so that the +/// initial and final MPT state tries can be reconstructed at the end of the execution. +/// An empty storage linked list is written as +/// [@U256_MAX, _, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. +/// Each slot is encoded using 5 values: +/// - 0: The account key +/// - 1: The slot key +/// - 2: The slot value. +/// - 3: The initial slot value. +/// - 4: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. + +%macro store_initial_slots + PUSH %%after + %jump(store_initial_slots) +%%after: +%endmacro + + +/// Iterates over the initial storage linked list and copies the slots values into +/// the initial values. +/// Computes the length of `SEGMENT_STORAGE_LINKED_LIST` and +/// checks against `GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE`. +/// It also checks that the next node address is current address + 5 +/// and that all keys are strictly increasing. +/// NOTE: It may be more efficient to check that the next node addres != U256_MAX +/// (i.e. node was not deleted) and ensure that no node with repeated key +/// is ever read. +global store_initial_slots: + // stack: retdest + PUSH @STORAGE_LINKED_LISTS_NODE_SIZE + PUSH @SEGMENT_STORAGE_LINKED_LIST + ADD + // stack: cur_len, retdest + PUSH @SEGMENT_STORAGE_LINKED_LIST + DUP1 + MLOAD_GENERAL + // stack: current_addr_key, current_node_ptr, cur_len, retdest + %assert_eq_const(@U256_MAX) + + // stack: current_node_ptr, cur_len', retdest + DUP1 + %next_slot + // stack: next_node_ptr, current_node_ptr, cur_len, retdest + DUP1 + SWAP2 + %next_initial_slot + %assert_eq(store_initial_slots_end) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, cur_len', retdest + +loop_store_initial_slots: + // stack: current_node_ptr, cur_len, retdest + DUP1 + %add_const(2) + MLOAD_GENERAL + // stack: value, current_node_ptr, cur_len, retdest + DUP2 + %add_const(@STORAGE_COPY_PAYLOAD_PTR) + // stack: cpy_value_ptr, value, current_node_ptr, cur_len, retdest + SWAP1 + MSTORE_GENERAL // Store cpy_value + // stack: current_node_ptr, cur_len, retdest + SWAP1 PUSH @STORAGE_LINKED_LISTS_NODE_SIZE + ADD + SWAP1 + // Check correctness of next node ptr and strict key monotonicity. + DUP1 + MLOAD_GENERAL + // stack: current_addr_key, current_node_ptr, cur_len', retdest + SWAP1 + DUP1 + %increment + MLOAD_GENERAL + // stack: current_slot_key, current_node_ptr, current_addr_key, cur_len', retdest + SWAP1 + DUP1 + %next_slot + // stack: next_node_ptr, current_node_ptr, current_slot_key, current_addr_key, cur_len', retdest + DUP1 + SWAP2 + %next_initial_slot + %assert_eq(store_initial_slots_end_pop_keys) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest + DUP1 + DUP1 + %increment + MLOAD_GENERAL + // stack: next_node_slot_key, next_node_ptr, next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest + SWAP1 + MLOAD_GENERAL + // stack: next_node_addr_key, next_node_slot_key, next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest + SWAP3 + LT + // stack: current_slot_key > next_node_slot_key, next_node_ptr, next_node_addr_key, current_addr_key, cur_len', retdest + SWAP2 + SWAP1 + SWAP3 + // stack: current_addr_key, next_node_addr_key, current_slot_key > next_node_slot_key, next_node_ptr, cur_len', retdest + DUP2 + DUP2 + EQ + // stack: current_addr_key == next_node_addr_key, current_addr_key, next_node_addr_key, current_slot_key > next_node_slot_key, next_node_ptr, cur_len', retdest + SWAP1 + SWAP3 + MUL // AND + // stack current_slot_key > next_node_slot_key AND current_addr_key == next_node_addr_key, next_node_addr_key, current_addr_key, next_node_ptr, cur_len', retdest + SWAP2 + LT + ADD // OR + %assert_nonzero + %jump(loop_store_initial_slots) + +store_initial_slots_end_pop_keys: + // stack: next_node_ptr, current_slot_key, current_addr_key, cur_len', retdest + SWAP2 + %pop2 + +store_initial_slots_end: + // stack: next_node_ptr, cur_len', retdest + %assert_eq_const(@SEGMENT_STORAGE_LINKED_LIST) + + // stack: cur_len, retdest + DUP1 + %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_STORAGE_LINKED_LIST_LEN) + %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) + JUMP + + +// Multiplies the value at the top of the stack, denoted by ptr/5, by 5 +// and aborts if ptr/5 >= (mem[@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE] - @SEGMENT_STORAGE_LINKED_LIST)/5. +// This way, @SEGMENT_STORAGE_LINKED_LIST + 5*ptr/5 must be pointing to the beginning of a node. +// TODO: Maybe we should check here if the node has been deleted. +%macro get_valid_slot_ptr + // stack: ptr/5 + DUP1 + PUSH 5 + PUSH @SEGMENT_STORAGE_LINKED_LIST + // stack: segment, 5, ptr/5, ptr/5 + %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 + DIV + // stack: accessed_strg_keys_len/5, ptr/5, ptr/5 + %assert_gt + %mul_const(5) + %add_const(@SEGMENT_STORAGE_LINKED_LIST) +%endmacro + +/// Inserts the pair (address_key, storage_key) and a new payload pointer into the linked list if it is not already present, +/// or modifies its payload if it was already present. +global insert_slot: + // stack: addr_key, key, value, retdest + PROVER_INPUT(linked_list::insert_slot) + // stack: pred_ptr/5, addr_key, key, value, retdest + %get_valid_slot_ptr + + // stack: pred_ptr, addr_key, key, value, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, value, retdest + DUP4 + GT + DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // we need to insert a new node. + %jumpi(insert_new_slot) + // stack: pred_addr_key, pred_ptr, addr_key, key, payload_ptr, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + // stack: pred_ptr, addr_key, key, value, retdest + DUP1 + %increment + MLOAD_GENERAL + // stack: pred_key, pred_ptr, addr_key, key, value, retdest + DUP1 DUP5 + GT + %jumpi(insert_new_slot) + // stack: pred_key, pred_ptr, addr_key, key, value, retdest + DUP4 + // We know that key <= pred_key. It must hold that pred_key == key. + %assert_eq + + // stack: pred_ptr, addr_key, key, value, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@STORAGE_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, slot_found_write_value) + // The storage key is not in the list. + PANIC + +insert_new_slot: + // stack: pred_addr or pred_key, pred_ptr, addr_key, key, value, retdest + POP + // get the value of the next address + %add_const(@STORAGE_NEXT_NODE_PTR) + // stack: next_ptr_ptr, addr_key, key, value, retdest + %mload_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) + DUP2 + MLOAD_GENERAL + // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + // Check that this is not a deleted node + DUP1 + %eq_const(@U256_MAX) + %assert_zero + DUP1 + MLOAD_GENERAL + // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + DUP1 + DUP6 + // Here, (addr_key > pred_addr_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). + // We should have (addr_key < next_addr_key), meaning the new value can be inserted between pred_ptr and next_ptr. + LT + %jumpi(next_node_ok) + // If addr_key <= next_addr_key, then it addr must be equal to next_addr + // stack: next_addr_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + DUP5 + %assert_eq + // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + DUP1 + %increment + MLOAD_GENERAL + // stack: next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + DUP1 // This is added just to have the correct stack in next_node_ok + DUP7 + // The next key must be strictly larger + %assert_lt + +next_node_ok: + // stack: next_addr or next_key, next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + POP + // stack: next_ptr, new_ptr, next_ptr_ptr, addr_key, key, value, retdest + SWAP2 + DUP2 + // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, addr_key, key, value, retdest + MSTORE_GENERAL + // stack: new_ptr, next_ptr, addr_key, key, value, retdest + // Write the address in the new node + DUP1 + DUP4 + MSTORE_GENERAL + // stack: new_ptr, next_ptr, addr_key, key, value, retdest + // Write the key in the new node + %increment + DUP1 + DUP5 + MSTORE_GENERAL + // stack: new_ptr + 1, next_ptr, addr_key, key, value, retdest + // Write the value in the linked list. + %increment + DUP1 %increment + // stack: new_ptr+3, new_value_ptr, next_ptr, addr_key, key, value, retdest + %stack (new_cloned_value_ptr, new_value_ptr, next_ptr, addr_key, key, value, retdest) + -> (value, new_cloned_value_ptr, value, new_value_ptr, new_cloned_value_ptr, next_ptr, retdest) + MSTORE_GENERAL // Store copied value. + MSTORE_GENERAL // Store value. + + // stack: new_ptr + 3, next_ptr, retdest + %increment + DUP1 + // stack: new_next_ptr_ptr, new_next_ptr_ptr, next_ptr, retdest + SWAP2 + MSTORE_GENERAL + // stack: new_next_ptr_ptr, retdest + %increment + %mstore_global_metadata(@GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE) + // stack: retdest + JUMP + +slot_found_write_value: + // stack: pred_ptr, addr_key, key, value, retdest + %add_const(2) + %stack (payload_ptr, addr_key, key, value) -> (value, payload_ptr) + MSTORE_GENERAL + // stack: retdest + JUMP + +%macro insert_slot + // stack: addr, slot, value + %addr_to_state_key + SWAP1 + %slot_to_storage_key + %stack (slot_key, addr_key, value) -> (addr_key, slot_key, value, %%after) + %jump(insert_slot) +%%after: + // stack: (empty) +%endmacro + +%macro insert_slot_from_addr_key + // stack: addr_key, slot_key, value + SWAP1 + %slot_to_storage_key + %stack (slot_key, addr_key, value) -> (addr_key, slot_key, value, %%after) + %jump(insert_slot) +%%after: + // stack: (empty) +%endmacro + + +%macro search_slot_from_addr_key + // stack: state_key, slot + SWAP1 + %slot_to_storage_key + %stack (storage_key, state_key) -> (state_key, storage_key, %%after) + %jump(search_slot) +%%after: +%endmacro + +/// Searches the pair (address_key, storage_key) in the storage the linked list. +/// Returns 0 if the storage key was inserted, or the current `value` if it was already present. +global search_slot: + // stack: addr_key, key, retdest + PROVER_INPUT(linked_list::search_slot) + // stack: pred_ptr/5, addr_key, key, retdest + %get_valid_slot_ptr + + // stack: pred_ptr, addr_key, key, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_addr_key, pred_addr_key, pred_ptr, addr_key, key, retdest + DUP4 + GT + DUP3 %eq_const(@SEGMENT_STORAGE_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // the slot was not found + %jumpi(slot_not_found) + // stack: pred_addr_key, pred_ptr, addr_key, key, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + // stack: pred_ptr, addr_key, key, retdest + DUP1 + %increment + MLOAD_GENERAL + // stack: pred_key, pred_ptr, addr_key, key, retdest + DUP1 DUP5 + GT + %jumpi(slot_not_found) + // stack: pred_key, pred_ptr, addr_key, key, retdest + DUP4 + // We know that key <= pred_key. It must hold that pred_key == key. + %assert_eq + // stack: pred_ptr, addr_key, key, retdest + + // stack: pred_ptr, addr_key, key, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@STORAGE_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, slot_found_no_write) + // The storage key is not in the list. + PANIC +slot_not_found: + // stack: pred_addr_or_pred_key, pred_ptr, addr_key, key, retdest + %stack (pred_addr_or_pred_key, pred_ptr, addr_key, key, retdest) + -> (retdest, 0) + JUMP + +slot_found_no_write: + // The slot was already in the list + // stack: pred_ptr, addr_key, key, retdest + // Load the old value + %add_const(2) + MLOAD_GENERAL + // stack: old_value, addr_key, key, retdest + %stack (old_value, addr_key, key, retdest) -> (retdest, old_value) + JUMP + +/// Removes the storage key and its value from the list. +/// Panics if the key is not in the list. +global remove_slot: + // stack: addr_key, key, retdest + PROVER_INPUT(linked_list::remove_slot) + // stack: pred_ptr/5, addr_key, key, retdest + %get_valid_slot_ptr + // stack: pred_ptr, addr_key, key, retdest + %add_const(@STORAGE_NEXT_NODE_PTR) + // stack: next_ptr_ptr, addr_key, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_ptr, next_ptr_ptr, addr_key, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_addr_key, next_ptr, next_ptr_ptr, addr_key, key, retdest + DUP4 + %assert_eq + // stack: next_ptr, next_ptr_ptr, addr_key, key, retdest + DUP1 + %increment + MLOAD_GENERAL + // stack: next_key, next_ptr, next_ptr_ptr, addr_key, key, retdest + DUP5 + %assert_eq + // stack: next_ptr, next_ptr_ptr, addr_key, key, retdest + %add_const(@STORAGE_NEXT_NODE_PTR) + // stack: next_next_ptr_ptr, next_ptr_ptr, addr_key, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, addr_key, key, retdest + // Mark the next node as deleted + SWAP1 + %mstore_u256_max + // stack: next_next_ptr, next_ptr_ptr, addr_key, key, retdest + MSTORE_GENERAL + %pop2 + JUMP + +%macro remove_slot_from_addr_key + // stack: addr_key, slot + SWAP1 + %slot_to_storage_key + %stack (key, addr_key) -> (addr_key, key, %%after) + %jump(remove_slot) +%%after: +%endmacro + +%macro read_slot_from_current_addr + // stack: slot + %slot_to_storage_key + %stack (storage_key) -> (storage_key, %%after) + %address + %addr_to_state_key + // stack: addr_key, storage_key, %%after + %jump(search_slot) +%%after: + // stack: slot_value +%endmacro + +%macro read_slot_from_addr + // stack: address, slot + SWAP1 + %slot_to_storage_key + %stack (storage_key, address) -> (address, storage_key, %%after) + %addr_to_state_key + // stack: addr_key, storage_key, %%after + %jump(search_slot) +%%after: + // stack: slot_value +%endmacro + +%macro read_slot_from_addr_key + // stack: state_key, slot + SWAP1 + %slot_to_storage_key + %stack (storage_key, state_key) -> (state_key, storage_key, %%after) + %jump(search_slot) +%%after: + // stack: slot_ptr +%endmacro + +%macro first_slot + // stack: empty + PUSH @SEGMENT_STORAGE_LINKED_LIST + %next_slot +%endmacro + +%macro first_initial_slot + // stack: empty + PUSH @SEGMENT_STORAGE_LINKED_LIST + %next_initial_slot +%endmacro + +%macro next_slot + // stack: node_ptr + %add_const(@STORAGE_NEXT_NODE_PTR) + MLOAD_GENERAL + // stack: next_node_ptr +%endmacro + +%macro next_initial_slot + // stack: node_ptr + %add_const(@STORAGE_LINKED_LISTS_NODE_SIZE) + // stack: next_node_ptr +%endmacro \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm new file mode 100644 index 000000000..701bd4193 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm @@ -0,0 +1,293 @@ +%macro smt_delete_state + %stack (key) -> (key, %%after) + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) // node_ptr + // stack: node_ptr, key, retdest + %jump(smt_delete) +%%after: + // stack: new_node_ptr + %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + // stack: (emtpy) +%endmacro + +// Return a copy of the given node with the given key deleted. +// Assumes that the key is in the SMT. +// +// Pre stack: node_ptr, key, retdest +// Post stack: updated_node_ptr +global smt_delete: + // stack: node_ptr, key, retdest + SWAP1 %split_key + %stack (k0, k1, k2, k3, node_ptr) -> (node_ptr, 0, k0, k1, k2, k3) +smt_delete_with_keys: + // stack: node_ptr, level, ks, retdest + DUP1 %mload_trie_data + // stack: node_type, node_ptr, level, ks, retdest + // Increment node_ptr, so it points to the node payload instead of its type. + SWAP1 %increment SWAP1 + // stack: node_type, node_payload_ptr, level, ks, retdest + + DUP1 %eq_const(@SMT_NODE_INTERNAL) %jumpi(smt_delete_internal) + %eq_const(@SMT_NODE_LEAF) %jumpi(smt_delete_leaf) + PANIC // Should never happen. + +smt_delete_leaf: + // stack: node_payload_ptr, level, ks, retdest + %pop6 + PUSH 0 // empty node ptr + SWAP1 JUMP + +smt_delete_internal: + // stack: node_type, node_payload_ptr, level, ks, retdest + POP + // stack: node_payload_ptr, level, ks, retdest + DUP2 %and_const(3) // level mod 4 + // stack: level%4, node_payload_ptr, level, ks, retdest + DUP1 %eq_const(0) %jumpi(smt_delete_internal_0) + DUP1 %eq_const(1) %jumpi(smt_delete_internal_1) + DUP1 %eq_const(2) %jumpi(smt_delete_internal_2) + %eq_const(3) %jumpi(smt_delete_internal_3) + PANIC +smt_delete_internal_0: + // stack: level%4, node_payload_ptr, level, ks, retdest + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k0, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk0, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, newk0, k1, k2, k3 ) + %jump(smt_delete_internal_contd) +smt_delete_internal_1: + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k1, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk1, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, newk1, k2, k3 ) + %jump(smt_delete_internal_contd) +smt_delete_internal_2: + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k2, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk2, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, newk2, k3 ) + %jump(smt_delete_internal_contd) +smt_delete_internal_3: + %stack (node_payload_ptr, level, k0, k1, k2, k3 ) -> (k3, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk3, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, k2, newk3 ) +smt_delete_internal_contd: + //stack: bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + PUSH internal_update + //stack: internal_update, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %rep 7 + DUP8 + %endrep + //stack: bit, node_payload_ptr, level, k0, k1, k2, k3, internal_update, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + ADD + //stack: child_ptr_ptr, level, k0, k1, k2, k3, internal_update, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %mload_trie_data + //stack: child_ptr, level, k0, k1, k2, k3, internal_update, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + SWAP1 %increment SWAP1 + //stack: child_ptr, level+1, k0, k1, k2, k3, internal_update, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %jump(smt_delete_with_keys) + +// Update the internal node, possibly deleting it, or returning a leaf node. +internal_update: + // Update the child first. + //stack: deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP2 PUSH 1 SUB + //stack: 1-bit, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP4 ADD + //stack: sibling_ptr_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %mload_trie_data DUP1 %mload_trie_data + //stack: sibling_node_type, sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP1 %eq_const(@SMT_NODE_HASH) %jumpi(sibling_is_hash) + DUP1 %eq_const(@SMT_NODE_LEAF) %jumpi(sibling_is_leaf) + %eq_const(@SMT_NODE_INTERNAL) %jumpi(sibling_is_internal) + PANIC // Should never happen. +sibling_is_internal: + //stack: sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP +insert_child: + //stack: deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %stack (deleted_child_ptr, bit, node_payload_ptr) -> (node_payload_ptr, bit, deleted_child_ptr, node_payload_ptr) + ADD %mstore_trie_data + // stack: node_payload_ptr, level, ks, retdest + %decrement + %stack (node_ptr, level, k0, k1, k2, k3, retdest) -> (retdest, node_ptr) + JUMP + +sibling_is_hash: + // stack: sibling_node_type, sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP + //stack: sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %increment %mload_trie_data + // stack: hash, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %jumpi(insert_child) // Sibling is non-empty hash node. +sibling_is_empty: + // stack: deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP1 %mload_trie_data + // stack: deleted_child_node_type, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP1 %eq_const(@SMT_NODE_HASH) %jumpi(sibling_is_empty_child_is_hash) + DUP1 %eq_const(@SMT_NODE_LEAF) %jumpi(sibling_is_empty_child_is_leaf) +sibling_is_empty_child_is_internal: + // stack: deleted_child_node_type, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP + // stack: deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %jump(insert_child) + +sibling_is_empty_child_is_hash: + // stack: deleted_child_node_type, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP + // stack: deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP1 %increment %mload_trie_data + // stack: hash, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %jumpi(insert_child) +sibling_is_empty_child_is_empty: + // We can just delete this node. + // stack: deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %pop8 + SWAP1 PUSH 0 + // stack: retdest, 0 + JUMP + +sibling_is_empty_child_is_leaf: + // stack: deleted_child_node_type, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP + // stack: deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %increment + // stack: deleted_child_key_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP4 + // stack: level, deleted_child_key_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP3 + // stack: bit, level, deleted_child_key_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP3 %mload_trie_data + // stack: child_key, bit, level, deleted_child_key_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %recombine_key + // stack: new_child_key, deleted_child_key_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP2 %mstore_trie_data + // stack: deleted_child_key_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %decrement + // stack: deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + SWAP7 + // stack: k3, bit, node_payload_ptr, level, k0, k1, k2, deleted_child_ptr, retdest + %pop7 + // stack: deleted_child_ptr, retdest + SWAP1 JUMP + +sibling_is_leaf: + // stack: sibling_node_type, sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP + // stack: sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + DUP2 %is_non_empty_node + // stack: child_is_non_empty, sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %jumpi(sibling_is_leaf_child_is_non_empty) +sibling_is_leaf_child_is_empty: + // stack: sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + %increment + // stack: sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP5 + // stack: level, sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP4 + // stack: bit, level, sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + PUSH 1 SUB + // stack: obit, level, sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP3 %mload_trie_data + // stack: sibling_key, obit, level, sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %recombine_key + // stack: new_key, sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + DUP2 %mstore_trie_data + // stack: sibling_key_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + %decrement + // stack: sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + SWAP8 + // stack: k3, deleted_child_ptr, bit, node_payload_ptr, level, k0, k1, k2, sibling_ptr, retdest + %pop8 + // stack: sibling_ptr, retdest + SWAP1 JUMP + +sibling_is_leaf_child_is_non_empty: + // stack: sibling_ptr, deleted_child_ptr, bit, node_payload_ptr, level, ks, retdest + POP + // stack: deleted_child_ptr, node_payload_ptr, bit, retdest + %jump(insert_child) + + +global delete_account: + %stack (address, retdest) -> (address, retdest) + DUP1 %key_nonce + // stack: key_nonce, address, retdest + DUP1 %smt_read_state ISZERO %jumpi(zero_nonce) + // stack: key_nonce, address, retdest + DUP1 %smt_delete_state + // stack: key_nonce, address, retdest +zero_nonce: + // stack: key_nonce, address, retdest + POP + // stack: address, retdest + DUP1 %key_balance + // stack: key_balance, address, retdest + DUP1 %smt_read_state ISZERO %jumpi(zero_balance) + // stack: key_balance, address, retdest + DUP1 %smt_delete_state + // stack: key_balance, address, retdest +zero_balance: + // stack: key_balance, address, retdest + POP + // stack: address, retdest + DUP1 %key_code + // stack: key_code, address, retdest + DUP1 %smt_read_state ISZERO %jumpi(zero_code) + // stack: key_code, address, retdest + DUP1 %smt_delete_state + // stack: key_code, address, retdest +zero_code: + // stack: key_code, address, retdest + POP + // stack: address, retdest + DUP1 %key_code_length + // stack: key_code_length, address, retdest + DUP1 %smt_read_state ISZERO %jumpi(zero_code_length) + // stack: key_code_length, address, retdest + DUP1 %smt_delete_state +zero_code_length: + // N.B.: We don't delete the storage, since there's no way of knowing keys used. + // stack: key_code_length, address, retdest + POP + // stack: address, retdest + %mload_global_metadata(@GLOBAL_METADATA_NEW_STORAGE_SLOTS_LEN) + // stack: slots_len, address, retdest + PUSH 0 + // stack: i, slots_len, address, retdest +delete_storage_slots_loop: + // stack: i, slots_len, address, retdest + DUP2 DUP2 EQ %jumpi(delete_storage_slots_loop_end) + // stack: i, slots_len, address, retdest + DUP1 %add_const(@SEGMENT_NEW_STORAGE_SLOTS) + // stack: addr_index, i, slots_len, address, retdest + MLOAD_GENERAL + // stack: slot_addr, i, slots_len, address, retdest + DUP4 EQ + // stack: address==slot_addr, i, slots_len, address, retdest + %jumpi(delete_storage_slot) + // stack: i, slots_len, address, retdest + %add_const(2) %jump(delete_storage_slots_loop) +delete_storage_slot: + // stack: i, slots_len, address, retdest + DUP1 %increment %add_const(@SEGMENT_NEW_STORAGE_SLOTS) + // stack: slot_index, i, slots_len, address, retdest + MLOAD_GENERAL + // stack: slot, i, slots_len, address, retdest + DUP4 %key_storage + // stack: key_storage, i, slots_len, address, retdest + DUP1 %smt_read_state ISZERO %jumpi(zero_slot) + // stack: key_storage, i, slots_len, address, retdest + DUP1 %smt_delete_state +zero_slot: + // stack: key_storage, i, slots_len, address, retdest + POP + // stack: i, slots_len, address, retdest + %add_const(2) %jump(delete_storage_slots_loop) + +delete_storage_slots_loop_end: + // stack: i, slots_len, address, retdest + %pop3 JUMP + +%macro delete_account + %stack (address) -> (address, %%after) + %jump(delete_account) +%%after: + // stack: (empty) +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm new file mode 100644 index 000000000..08dbfd1a1 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm @@ -0,0 +1,85 @@ +%macro smt_hash_state + %stack (cur_len) -> (cur_len, %%after) + %jump(smt_hash_state) +%%after: +%endmacro + +// Root hash of the state SMT. +global smt_hash_state: + // stack: cur_len, retdest + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + +// Root hash of SMT stored at `trie_data[ptr]`. +// Pseudocode: +// ``` +// hash( HashNode { h } ) = h +// hash( InternalNode { left, right } ) = Poseidon(hash(left) || hash(right) || [0,0,0,0]) +// hash( Leaf { rem_key, val_hash } ) = Poseidon(rem_key || val_hash || [1,0,0,0]) +// ``` +global smt_hash: + // stack: ptr, cur_len, retdest + DUP1 + %mload_trie_data + // stack: node, node_ptr, cur_len, retdest + DUP1 %eq_const(@SMT_NODE_HASH) %jumpi(smt_hash_hash) + DUP1 %eq_const(@SMT_NODE_INTERNAL) %jumpi(smt_hash_internal) + %eq_const(@SMT_NODE_LEAF) %jumpi(smt_hash_leaf) +smt_hash_unknown_node_type: + PANIC + +smt_hash_hash: + // stack: node, node_ptr, cur_len, retdest + POP + // stack: node_ptr, cur_len, retdest + SWAP1 %add_const(2) SWAP1 + // stack: node_ptr, cur_len, retdest + %increment + // stack: node_ptr+1, cur_len, retdest + %mload_trie_data + %stack (hash, cur_len, retdest) -> (retdest, hash, cur_len) + JUMP + +smt_hash_internal: + // stack: node, node_ptr, cur_len, retdest + POP + // stack: node_ptr, cur_len, retdest + SWAP1 %add_const(3) SWAP1 + %increment + // stack: node_ptr+1, cur_len, retdest + DUP1 + %mload_trie_data + %stack (left_child_ptr, node_ptr_plus_1, cur_len, retdest) -> (left_child_ptr, cur_len, smt_hash_internal_after_left, node_ptr_plus_1, retdest) + %jump(smt_hash) +smt_hash_internal_after_left: + %stack (left_hash, cur_len, node_ptr_plus_1, retdest) -> (node_ptr_plus_1, left_hash, cur_len, retdest) + %increment + // stack: node_ptr+2, left_hash, cur_len, retdest + %mload_trie_data + %stack (right_child_ptr, left_hash, cur_len, retdest) -> (right_child_ptr, cur_len, smt_hash_internal_after_right, left_hash, retdest) + %jump(smt_hash) +smt_hash_internal_after_right: + %stack (right_hash, cur_len, left_hash) -> (left_hash, right_hash, 0, cur_len) + POSEIDON + %stack (hash, cur_len, retdest) -> (retdest, hash, cur_len) + JUMP + +smt_hash_leaf: + // stack: node_ptr, cur_len, retdest + SWAP1 %add_const(3) SWAP1 + // stack: node_ptr, cur_len, retdest + %increment + // stack: node_ptr+1, cur_len, retdest + DUP1 %increment + // stack: node_ptr+2, node_ptr+1, cur_len, retdest + %mload_trie_data + // stack: value, node_ptr+1, cur_len, retdest + SWAP1 + // stack: node_ptr+1, value, cur_len, retdest + %mload_trie_data + %stack (rem_key, value) -> (value, smt_hash_leaf_contd, rem_key) + %jump(hash_limbs) +smt_hash_leaf_contd: + %stack (value_hash, rem_key) -> (rem_key, value_hash, 1) + POSEIDON + %stack (hash, cur_len, retdest) -> (retdest, hash, cur_len) + JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/insert.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/insert.asm new file mode 100644 index 000000000..20589b083 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/insert.asm @@ -0,0 +1,175 @@ +// Insert a key-value pair in the state SMT. +global smt_insert_state: + // stack: key, value, retdest + DUP2 ISZERO %jumpi(insert_zero) + // stack: key, value, retdest + %stack (key, value) -> (key, value, smt_insert_state_after) + %split_key + // stack: k0, k1, k2, k3, value, smt_insert_state_after, retdest + PUSH 0 + // stack: level, k0, k1, k2, k3, value, smt_insert_state_after, retdest + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) // node_ptr + // stack: node_ptr, level, k0, k1, k2, k3, value, smt_insert_state_after, retdest + %jump(smt_insert) + +smt_insert_state_after: + // stack: root_ptr, retdest + %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + // stack: retdest + JUMP + +%macro smt_insert_state + %stack (key, value_ptr) -> (key, value_ptr, %%after) + %jump(smt_insert_state) +%%after: +%endmacro + +// Insert a key-value pair in the SMT at `trie_data[node_ptr]`. +// Pseudocode: +// ``` +// insert( HashNode { h }, key, value ) = if h == 0 then Leaf { key, value } else PANIC +// insert( InternalNode { left, right }, key, value ) = if key&1 { insert( right, key>>1, value ) } else { insert( left, key>>1, value ) } +// insert( Leaf { key', value' }, key, value ) = { +// let internal = new InternalNode; +// insert(internal, key', value'); +// insert(internal, key, value); +// return internal;} +// ``` +global smt_insert: + // stack: node_ptr, level, ks, value, retdest + DUP1 %mload_trie_data + // stack: node_type, node_ptr, level, ks, value, retdest + // Increment node_ptr, so it points to the node payload instead of its type. + SWAP1 %increment SWAP1 + // stack: node_type, node_payload_ptr, level, ks, value, retdest + + DUP1 %eq_const(@SMT_NODE_HASH) %jumpi(smt_insert_hash) + DUP1 %eq_const(@SMT_NODE_INTERNAL) %jumpi(smt_insert_internal) + DUP1 %eq_const(@SMT_NODE_LEAF) %jumpi(smt_insert_leaf) + PANIC + +smt_insert_hash: + // stack: node_type, node_payload_ptr, level, ks, value, retdest + POP + // stack: node_payload_ptr, level, ks, value, retdest + %mload_trie_data + // stack: hash, level, ks, value, retdest + ISZERO %jumpi(smt_insert_empty) + PANIC // Trying to insert in a non-empty hash node. +smt_insert_empty: + // stack: level, ks, value, retdest + POP + // stack: ks, value, retdest + %combine_key + // stack: key, value, retdest + %get_trie_data_size + // stack: index, key, value, retdest + PUSH @SMT_NODE_LEAF %append_to_trie_data + %stack (index, key, value) -> (key, value, index) + %append_to_trie_data // key + %append_to_trie_data // value + // stack: index, retdest + SWAP1 JUMP + +smt_insert_internal: + // stack: node_type, node_payload_ptr, level, ks, value, retdest + POP + // stack: node_payload_ptr, level, ks, value, retdest + DUP2 %and_const(3) // level mod 4 + // stack: level%4, node_payload_ptr, level, ks, value, retdest + DUP1 %eq_const(0) %jumpi(smt_insert_internal_0) + DUP1 %eq_const(1) %jumpi(smt_insert_internal_1) + DUP1 %eq_const(2) %jumpi(smt_insert_internal_2) + %eq_const(3) %jumpi(smt_insert_internal_3) + PANIC +smt_insert_internal_0: + // stack: level%4, node_payload_ptr, level, ks, value, retdest + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k0, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk0, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, newk0, k1, k2, k3 ) + %jump(smt_insert_internal_contd) +smt_insert_internal_1: + // stack: level%4, node_payload_ptr, level, ks, value, retdest + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k1, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk1, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, newk1, k2, k3 ) + %jump(smt_insert_internal_contd) +smt_insert_internal_2: + // stack: level%4, node_payload_ptr, level, ks, value, retdest + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k2, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk2, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, newk2, k3 ) + %jump(smt_insert_internal_contd) +smt_insert_internal_3: + // stack: level%4, node_payload_ptr, level, ks, value, retdest + %stack (node_payload_ptr, level, k0, k1, k2, k3 ) -> (k3, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk3, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, k2, newk3 ) + %jump(smt_insert_internal_contd) +smt_insert_internal_contd: + // stack: bit, node_payload_ptr, level, ks, value, retdest + DUP2 ADD + // stack: child_ptr_ptr, node_payload_ptr, level, ks, value, retdest + DUP1 %mload_trie_data + // stack: child_ptr, child_ptr_ptr, node_payload_ptr, level, ks, value, retdest + SWAP3 %increment SWAP3 + %stack (child_ptr, child_ptr_ptr, node_payload_ptr, level_plus_1, k0, k1, k2, k3, value, retdest) -> + (child_ptr, level_plus_1, k0, k1, k2, k3, value, smt_insert_internal_after, child_ptr_ptr, node_payload_ptr, retdest) + %jump(smt_insert) + +smt_insert_internal_after: + // stack: new_node_ptr, child_ptr_ptr, node_payload_ptr, retdest + SWAP1 %mstore_trie_data + // stack: node_payload_ptr, retdest + %decrement + SWAP1 JUMP + +smt_insert_leaf: + // stack: node_type, node_payload_ptr, level, ks, value, retdest + POP + %stack (node_payload_ptr, level, k0, k1, k2, k3, value) -> (k0, k1, k2, k3, node_payload_ptr, level, k0, k1, k2, k3, value) + %combine_key + // stack: rem_key, node_payload_ptr, level, ks, value, retdest + DUP2 %mload_trie_data + // stack: existing_key, rem_key, node_payload_ptr, level, ks, value, retdest + DUP2 DUP2 EQ %jumpi(smt_insert_leaf_same_key) + // stack: existing_key, rem_key, node_payload_ptr, level, ks, value, retdest + // We create an internal node with two empty children, and then we insert the two leaves. + %get_trie_data_size + // stack: index, existing_key, rem_key, node_payload_ptr, level, ks, value, retdest + PUSH @SMT_NODE_INTERNAL %append_to_trie_data + PUSH 0 %append_to_trie_data // Empty hash node + PUSH 0 %append_to_trie_data // Empty hash node + // stack: index, existing_key, rem_key, node_payload_ptr, level, ks, value, retdest + SWAP1 %split_key + // stack: existing_k0, existing_k1, existing_k2, existing_k3, index, rem_key, node_payload_ptr, level, ks, value, retdest + DUP7 %increment %mload_trie_data + // stack: existing_value, existing_k0, existing_k1, existing_k2, existing_k3, index, rem_key, node_payload_ptr, level, ks, value, retdest + DUP9 + %stack (level, existing_value, existing_k0, existing_k1, existing_k2, existing_k3, index) -> (index, level, existing_k0, existing_k1, existing_k2, existing_k3, existing_value, after_first_leaf) + %jump(smt_insert) +after_first_leaf: + // stack: internal_ptr, rem_key, node_payload_ptr, level, ks, value, retdest + %stack (internal_ptr, rem_key, node_payload_ptr, level, k0, k1, k2, k3, value) -> (internal_ptr, level, k0, k1, k2, k3, value) + %jump(smt_insert) + +smt_insert_leaf_same_key: + // stack: existing_key, rem_key, node_payload_ptr, level, ks, value, retdest + %pop2 + %stack (node_payload_ptr, level, k0, k1, k2, k3, value) -> (node_payload_ptr, value, node_payload_ptr) + %increment %mstore_trie_data + // stack: node_payload_ptr, retdest + %decrement + // stack: node_ptr, retdest + SWAP1 JUMP + +insert_zero: + // stack: key, value, retdest + DUP1 %smt_read_state %mload_trie_data %jumpi(delete) + // stack: key, value, retdest + %pop2 JUMP +delete: + // stack: key, value, retdest + %smt_delete_state + // stack: value, retdest + POP JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/keys.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/keys.asm new file mode 100644 index 000000000..0d8b09013 --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/keys.asm @@ -0,0 +1,131 @@ +/// See `smt_trie::keys.rs` for documentation. + +// addr = sum_{0<=i<5} a_i << (32i) +%macro key_balance + // stack: addr + PUSH 0x100000000 + // stack: u32max, addr + DUP1 DUP3 MOD + // stack: a_0, u32max, addr + DUP2 DUP4 %shr_const(32) MOD %shl_const(64) ADD + // stack: a_0 + a_1<<64, u32max, addr + DUP2 DUP4 %shr_const(64) MOD %shl_const(128) ADD + // stack: a_0 + a_1<<64 + a_2<<128, u32max, addr + DUP2 DUP4 %shr_const(96) MOD %shl_const(192) ADD + // stack: a_0 + a_1<<64 + a_2<<128 + a_3<<192, u32max, addr + SWAP2 %shr_const(128) + // stack: a_4, u32max, a_0 + a_1<<64 + a_2<<128 + a_3<<192 + %stack (y, u32max, x) -> (x, y, @POSEIDON_HASH_ZEROS) + POSEIDON +%endmacro + +// addr = sum_{0<=i<5} a_i << (32i) +%macro key_nonce + // stack: addr + PUSH 0x100000000 + // stack: u32max, addr + DUP1 DUP3 MOD + // stack: a_0, u32max, addr + DUP2 DUP4 %shr_const(32) MOD %shl_const(64) ADD + // stack: a_0 + a_1<<64, u32max, addr + DUP2 DUP4 %shr_const(64) MOD %shl_const(128) ADD + // stack: a_0 + a_1<<64 + a_2<<128, u32max, addr + DUP2 DUP4 %shr_const(96) MOD %shl_const(192) ADD + // stack: a_0 + a_1<<64 + a_2<<128 + a_3<<192, u32max, addr + SWAP2 %shr_const(128) + // stack: a_4, u32max, a_0 + a_1<<64 + a_2<<128 + a_3<<192 + %add_const(0x100000000000000000000000000000000) // SMT_KEY_NONCE (=1) << 128 + %stack (y, u32max, x) -> (x, y, @POSEIDON_HASH_ZEROS) + POSEIDON +%endmacro + +// addr = sum_{0<=i<5} a_i << (32i) +%macro key_code + // stack: addr + PUSH 0x100000000 + // stack: u32max, addr + DUP1 DUP3 MOD + // stack: a_0, u32max, addr + DUP2 DUP4 %shr_const(32) MOD %shl_const(64) ADD + // stack: a_0 + a_1<<64, u32max, addr + DUP2 DUP4 %shr_const(64) MOD %shl_const(128) ADD + // stack: a_0 + a_1<<64 + a_2<<128, u32max, addr + DUP2 DUP4 %shr_const(96) MOD %shl_const(192) ADD + // stack: a_0 + a_1<<64 + a_2<<128 + a_3<<192, u32max, addr + SWAP2 %shr_const(128) + // stack: a_4, u32max, a_0 + a_1<<64 + a_2<<128 + a_3<<192 + %add_const(0x200000000000000000000000000000000) // SMT_KEY_CODE (=2) << 128 + %stack (y, u32max, x) -> (x, y, @POSEIDON_HASH_ZEROS) + POSEIDON +%endmacro + +// addr = sum_{0<=i<5} a_i << (32i) +%macro key_code_length + // stack: addr + PUSH 0x100000000 + // stack: u32max, addr + DUP1 DUP3 MOD + // stack: a_0, u32max, addr + DUP2 DUP4 %shr_const(32) MOD %shl_const(64) ADD + // stack: a_0 + a_1<<64, u32max, addr + DUP2 DUP4 %shr_const(64) MOD %shl_const(128) ADD + // stack: a_0 + a_1<<64 + a_2<<128, u32max, addr + DUP2 DUP4 %shr_const(96) MOD %shl_const(192) ADD + // stack: a_0 + a_1<<64 + a_2<<128 + a_3<<192, u32max, addr + SWAP2 %shr_const(128) + // stack: a_4, u32max, a_0 + a_1<<64 + a_2<<128 + a_3<<192 + %add_const(0x400000000000000000000000000000000) // SMT_KEY_CODE_LENGTH (=4) << 128 + %stack (y, u32max, x) -> (x, y, @POSEIDON_HASH_ZEROS) + POSEIDON +%endmacro + +// addr = sum_{0<=i<5} a_i << (32i) +%macro key_storage + %stack (addr, slot) -> (slot, %%after, addr) + %jump(hash_limbs) +%%after: + // stack: capacity, addr + SWAP1 + // stack: addr, capacity + PUSH 0x100000000 + // stack: u32max, addr, capacity + DUP1 DUP3 MOD + // stack: a_0, u32max, addr + DUP2 DUP4 %shr_const(32) MOD %shl_const(64) ADD + // stack: a_0 + a_1<<64, u32max, addr + DUP2 DUP4 %shr_const(64) MOD %shl_const(128) ADD + // stack: a_0 + a_1<<64 + a_2<<128, u32max, addr + DUP2 DUP4 %shr_const(96) MOD %shl_const(192) ADD + // stack: a_0 + a_1<<64 + a_2<<128 + a_3<<192, u32max, addr + SWAP2 %shr_const(128) + // stack: a_4, u32max, a_0 + a_1<<64 + a_2<<128 + a_3<<192 + %add_const(0x300000000000000000000000000000000) // SMT_KEY_STORAGE (=3) << 128 + %stack (y, u32max, x, capacity) -> (x, y, capacity) + POSEIDON +%endmacro + +// slot = sum_{0<=i<8} s_i << (32i) +global hash_limbs: + // stack: slot, retdest + PUSH 0x100000000 + // stack: u32max, slot, retdest + DUP1 DUP3 MOD + // stack: s_0, u32max, slot + DUP2 DUP4 %shr_const(32) MOD %shl_const(64) ADD + // stack: s_0 + s_1<<64, u32max, slot + DUP2 DUP4 %shr_const(64) MOD %shl_const(128) ADD + // stack: s_0 + s_1<<64 + s_2<<128, u32max, slot + DUP2 DUP4 %shr_const(96) MOD %shl_const(192) ADD + // stack: s_0 + s_1<<64 + s_2<<128 + s_3<<192, u32max, slot + DUP2 DUP4 %shr_const(128) MOD + // stack: s_4, s_0 + s_1<<64 + s_2<<128 + s_3<<192, u32max, slot + DUP3 DUP5 %shr_const(160) MOD %shl_const(64) ADD + // stack: s_4 + s_5<<64, s_0 + s_1<<64 + s_2<<128 + s_3<<192, u32max, slot + DUP3 DUP5 %shr_const(192) MOD %shl_const(128) ADD + // stack: s_4 + s_5<<64 + s_6<<128, s_0 + s_1<<64 + s_2<<128 + s_3<<192, u32max, slot + DUP3 DUP5 %shr_const(224) MOD %shl_const(192) ADD + // stack: s_4 + s_5<<64 + s_6<<128 + s_7<<192, s_0 + s_1<<64 + s_2<<128 + s_3<<192, u32max, slot + %stack (b, a, u32max, slot) -> (a, b, 0) + POSEIDON + // stack: hash, retdest + SWAP1 JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm new file mode 100644 index 000000000..cd4bce33d --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm @@ -0,0 +1,110 @@ +// Given a key, return a pointer to the associated SMT entry. +// Returns 0 if the key is not in the SMT. +global smt_read_state: + // stack: key, retdest + %split_key + // stack: k0, k1, k2, k3, retdest + PUSH 0 + // stack: level, k0, k1, k2, k3, retdest + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) // node_ptr + // stack: node_ptr, level, k0, k1, k2, k3, retdest + %jump(smt_read) + +// Convenience macro to call smt_read_state and return where we left off. +%macro smt_read_state + %stack (key) -> (key, %%after) + %jump(smt_read_state) +%%after: +%endmacro + +// Return a pointer to the data at the given key in the SMT at `trie_data[node_ptr]`. +// Pseudocode: +// ``` +// read( HashNode { h }, key ) = if h == 0 then 0 else PANIC +// read( InternalNode { left, right }, key ) = if key&1 { read( right, key>>1 ) } else { read( left, key>>1 ) } +// read( Leaf { rem_key', value }, key ) = if rem_key == rem_key' then &value else 0 +// ``` +global smt_read: + // stack: node_ptr, level, ks, retdest + DUP1 %mload_trie_data + // stack: node_type, node_ptr, level, ks, retdest + // Increment node_ptr, so it points to the node payload instead of its type. + SWAP1 %increment SWAP1 + // stack: node_type, node_payload_ptr, level, ks, retdest + + DUP1 %eq_const(@SMT_NODE_HASH) %jumpi(smt_read_hash) + DUP1 %eq_const(@SMT_NODE_INTERNAL) %jumpi(smt_read_internal) + %eq_const(@SMT_NODE_LEAF) %jumpi(smt_read_leaf) + PANIC + +smt_read_hash: + // stack: node_type, node_payload_ptr, level, ks, retdest + POP + // stack: node_payload_ptr, level, ks, retdest + %mload_trie_data + // stack: hash, level, ks, retdest + ISZERO %jumpi(smt_read_empty) + PANIC // Trying to read a non-empty hash node. Should never happen. + +smt_read_empty: + %stack (level, k0, k1, k2, k3, retdest) -> (retdest, 0) + JUMP + +smt_read_internal: + // stack: node_type, node_payload_ptr, level, ks, retdest + POP + // stack: node_payload_ptr, level, ks, retdest + DUP2 %and_const(3) // level mod 4 + // stack: level%4, node_payload_ptr, level, ks, retdest + DUP1 %eq_const(0) %jumpi(smt_read_internal_0) + DUP1 %eq_const(1) %jumpi(smt_read_internal_1) + DUP1 %eq_const(2) %jumpi(smt_read_internal_2) + DUP1 %eq_const(3) %jumpi(smt_read_internal_3) + PANIC +smt_read_internal_0: + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k0, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk0, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, newk0, k1, k2, k3 ) + %jump(smt_read_internal_contd) +smt_read_internal_1: + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k1, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk1, node_payload_ptr, level , k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, newk1, k2, k3 ) + %jump(smt_read_internal_contd) +smt_read_internal_2: + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k2, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk2, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, newk2, k3 ) + %jump(smt_read_internal_contd) +smt_read_internal_3: + %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k3, node_payload_ptr, level, k0, k1, k2, k3 ) + %pop_bit + %stack (bit, newk3, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, k2, newk3 ) +smt_read_internal_contd: + // stack: bit, node_payload_ptr, level, k0, k1, k2, k3, retdest + ADD + // stack: child_ptr_ptr, level, k0, k1, k2, k3, retdest + %mload_trie_data + // stack: child_ptr, level, k0, k1, k2, k3, retdest + SWAP1 %increment SWAP1 + // stack: child_ptr, level+1, k0, k1, k2, k3, retdest + %jump(smt_read) + +smt_read_leaf: + // stack: node_payload_ptr, level, ks, retdest + DUP1 %mload_trie_data + // stack: rem_key, node_payload_ptr, level, ks, retdest + SWAP1 + // stack: node_payload_ptr, rem_key, level, ks, retdest + %increment + %stack (value_ptr, rem_key, level, k0, k1, k2, k3) -> (k0, k1, k2, k3, rem_key, value_ptr) + %combine_key + // stack: this_rem_key, rem_key, value_ptr, retdest + EQ %jumpi(smt_read_existing_leaf) +smt_read_non_existing_leaf: + %stack (value_ptr, retdest) -> (retdest, 0) + JUMP + +smt_read_existing_leaf: + // stack: value_ptr, retdest + SWAP1 JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/utils.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/utils.asm new file mode 100644 index 000000000..4f8c2832e --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/utils.asm @@ -0,0 +1,129 @@ +// Input: x +// Output: (x&1, x>>1) +%macro pop_bit + // stack: key + DUP1 %shr_const(1) + // stack: key>>1, key + SWAP1 %mod_const(2) + // stack: key&1, key>>1 +%endmacro + +// Returns a non-zero value if the node is non-empty. +%macro is_non_empty_node + // stack: node_ptr + DUP1 %mload_trie_data %jumpi(%%end) // If the node is not a hash node, node_ptr is non-zero. + // The node is a hash node + // stack: node_ptr + %increment %mload_trie_data + // stack: hash +%%end: +%endmacro + +// Input: key = k0 + k1.2^64 + k2.2^128 + k3.2^192, with 0<=ki<2^64. +// Output: (k0, k1, k2, k3) +%macro split_key + // stack: key + DUP1 %shr_const(128) %mod_const(0x10000000000000000) + // stack: k2, key + DUP2 %shr_const(64) %mod_const(0x10000000000000000) + // stack: k1, k2, key + DUP3 %shr_const(192) + // stack: k3, k1, k2, key + SWAP3 %mod_const(0x10000000000000000) + // stack: k0, k1, k2, k3 +%endmacro + +// Input: (k0, k1, k2, k3) +// Output: k0 + k1.2^64 + k2.2^128 + k3.2^192 +%macro combine_key + // stack: k0, k1, k2, k3 + SWAP1 %shl_const(64) ADD + // stack: k0 + k1<<64, k2, k3 + SWAP1 %shl_const(128) ADD + // stack: k0 + k1<<64 + k2<<128, k3 + SWAP1 %shl_const(192) ADD + // stack: k0 + k1<<64 + k2<<128 + k3<<192 +%endmacro + + +// Pseudocode: +// ``` +// def recombine_key(key, bit, level): +// k0, k1, k2, k3 = [(key>>(64*i))&(2**64-1) for i in range(4)] +// match level%4: +// 0 => k0 = 2*k0 + bit +// 1 => k1 = 2*k1 + bit +// 2 => k2 = 2*k2 + bit +// 3 => k3 = 2*k3 + bit +// return k0 + (k1<<64) + (k2<<128) + (k3<<192) +// ``` +%macro recombine_key + // stack: key, bit, level + SWAP1 + // stack: bit, key, level + SWAP2 + // stack: level, key, bit + %mod_const(4) + // stack: level%4, key, bit + DUP1 %eq_const(0) %jumpi(%%recombine_key_0) + DUP1 %eq_const(1) %jumpi(%%recombine_key_1) + DUP1 %eq_const(2) %jumpi(%%recombine_key_2) + DUP1 %eq_const(3) %jumpi(%%recombine_key_3) + PANIC +%%recombine_key_0: + // stack: level%4, key, bit + POP + // stack: key, bit + %split_key + // stack: k0, k1, k2, k3, bit + %shl_const(1) + // stack: k0<<1, k1, k2, k3, bit + DUP5 ADD + // stack: k0<<1 + bit, k1, k2, k3, bit + %combine_key + %stack (newkey, bit) -> (newkey) + %jump(%%after) +%%recombine_key_1: + // stack: level%4, key, bit + POP + // stack: key, bit + %split_key + // stack: k0, k1, k2, k3, bit + DUP2 %shl_const(1) + // stack: k1<<1, k0, k1, k2, k3, bit + DUP6 ADD + // stack: k1<<1 + bit, k0, k1, k2, k3, bit + SWAP2 POP + %combine_key + %stack (newkey, bit) -> (newkey) + %jump(%%after) +%%recombine_key_2: + // stack: key, bit + POP + // stack: key, bit + %split_key + // stack: k0, k1, k2, k3, bit + DUP3 %shl_const(1) + // stack: k2<<1, k0, k1, k2, k3, bit + DUP6 ADD + // stack: k2<<1 + bit, k0, k1, k2, k3, bit + SWAP3 POP + %combine_key + %stack (newkey, bit) -> (newkey) + %jump(%%after) +%%recombine_key_3: + // stack: key, bit + POP + // stack: key, bit + %split_key + // stack: k0, k1, k2, k3, bit + DUP4 %shl_const(1) + // stack: k3<<1, k0, k1, k2, k3, bit + DUP6 ADD + // stack: k3<<1 + bit, k0, k1, k2, k3, bit + SWAP4 POP + %combine_key + %stack (newkey, bit) -> (newkey) +%%after: + // stack: newkey +%endmacro diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs new file mode 100644 index 000000000..0ec3b70ab --- /dev/null +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -0,0 +1,318 @@ +#![cfg(feature = "cdk_erigon")] + +use std::collections::HashMap; +use std::str::FromStr; +use std::time::Duration; + +use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp}; +use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; +use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; +use evm_arithmetization::prover::testing::prove_all_segments; +#[cfg(feature = "eth_mainnet")] +use evm_arithmetization::testing_utils::beacon_roots_contract_from_storage; +use evm_arithmetization::testing_utils::{ + beacon_roots_account_nibbles, create_account_storage, init_logger, + preinitialized_state_and_storage_tries, sd2u, update_beacon_roots_account_storage, +}; +use evm_arithmetization::util::h2u; +use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; +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::field::types::Field; +use plonky2::plonk::config::KeccakGoldilocksConfig; +use plonky2::util::timing::TimingTree; +use smt_trie::code::hash_bytecode_u256; +use smt_trie::db::{Db, MemoryDb}; +use smt_trie::keys::{key_balance, key_code, key_code_length, key_nonce, key_storage}; +use smt_trie::smt::Smt; +use smt_trie::utils::hashout2u; + +type F = GoldilocksField; +const D: usize = 2; +type C = KeccakGoldilocksConfig; + +/// Test a simple ERC20 transfer. +/// Used the following Solidity code: +/// ```solidity +/// pragma solidity ^0.8.13; +/// import "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +/// contract Token is ERC20 { +/// constructor() ERC20("Token", "TKN") { +/// _mint(msg.sender, 1_000_000 ether); +/// } +/// } +/// contract Giver { +/// Token public token; +/// constructor(address _token) { +/// token = Token(_token); +/// } +/// function send(uint256 amount) public { +/// token.transfer(0x1f9090aaE28b8a3dCeaDf281B0F12828e676c326, amount); +/// } +/// } +/// ``` +#[test] +fn test_erc20() -> anyhow::Result<()> { + init_logger(); + + let all_stark = AllStark::::default(); + let config = StarkConfig::standard_fast_config(); + + let beneficiary = hex!("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + let sender = hex!("70997970C51812dc3A010C7d01b50e0d17dc79C8"); + let giver = hex!("e7f1725E7734CE288F8367e1Bb143E90bb3F0512"); + let token = hex!("5FbDB2315678afecb367f032d93F642f64180aa3"); + + let mut state_smt_before = Smt::::default(); + set_account( + &mut state_smt_before, + H160(sender), + &sender_account(), + &HashMap::new(), + ); + set_account( + &mut state_smt_before, + H160(giver), + &giver_account(), + &giver_storage(), + ); + set_account( + &mut state_smt_before, + H160(token), + &token_account(), + &token_storage(), + ); + + let tries_before = TrieInputs { + state_trie: state_smt_before, + transactions_trie: HashedPartialTrie::from(Node::Empty), + receipts_trie: HashedPartialTrie::from(Node::Empty), + }; + + let txn = signed_tx(); + + let gas_used = 56_499.into(); + let bloom = bloom(); + let block_metadata = BlockMetadata { + block_beneficiary: Address::from(beneficiary), + block_timestamp: 0x03e8.into(), + block_number: 1.into(), + block_difficulty: 0x020000.into(), + block_random: H256::from_uint(&0x020000.into()), + block_gaslimit: 0xff112233u32.into(), + block_chain_id: 1.into(), + block_base_fee: 0xa.into(), + block_gas_used: gas_used, + block_bloom: bloom, + ..Default::default() + }; + + let contract_code = [giver_bytecode(), token_bytecode(), vec![]] + .map(|v| (keccak(v.clone()), v)) + .into(); + + let expected_smt_after: Smt = { + let mut smt = Smt::default(); + let sender_account = sender_account(); + let sender_account_after = AccountRlp { + nonce: sender_account.nonce + 1, + balance: sender_account.balance - gas_used * 0xa, + ..sender_account + }; + set_account( + &mut smt, + H160(sender), + &sender_account_after, + &HashMap::new(), + ); + set_account(&mut smt, H160(giver), &giver_account(), &giver_storage()); + set_account( + &mut smt, + H160(token), + &token_account(), + &token_storage_after(), + ); + + smt + }; + + let receipt_0 = LegacyReceiptRlp { + status: true, + cum_gas_used: gas_used, + bloom: bloom_bytes().to_vec().into(), + logs: vec![LogRlp { + address: H160::from_str("0x5fbdb2315678afecb367f032d93f642f64180aa3").unwrap(), + topics: vec![ + H256::from_str( + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + ) + .unwrap(), + H256::from_str( + "0x000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f0512", + ) + .unwrap(), + H256::from_str( + "0x0000000000000000000000001f9090aae28b8a3dceadf281b0f12828e676c326", + ) + .unwrap(), + ], + data: hex!("0000000000000000000000000000000000000000000000056bc75e2d63100000") + .to_vec() + .into(), + }], + }; + let mut receipts_trie = HashedPartialTrie::from(Node::Empty); + receipts_trie.insert(Nibbles::from_str("0x80").unwrap(), receipt_0.encode(2))?; + let transactions_trie: HashedPartialTrie = Node::Leaf { + nibbles: Nibbles::from_str("0x80").unwrap(), + value: txn.to_vec(), + } + .into(); + + let trie_roots_after = TrieRoots { + state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), + transactions_root: transactions_trie.hash(), + receipts_root: receipts_trie.hash(), + }; + + let inputs = GenerationInputs:: { + signed_txns: vec![txn.to_vec()], + burn_addr: None, + withdrawals: vec![], + ger_data: None, + tries: tries_before, + trie_roots_after, + contract_code, + checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(), + checkpoint_consolidated_hash: EMPTY_CONSOLIDATED_BLOCKHASH.map(F::from_canonical_u64), + block_metadata, + txn_number_before: 0.into(), + gas_used_before: 0.into(), + gas_used_after: gas_used, + block_hashes: BlockHashes { + prev_hashes: vec![H256::default(); 256], + cur_hash: H256::default(), + }, + }; + + let max_cpu_len_log = 20; + let mut timing = TimingTree::new("prove", log::Level::Debug); + + let proofs = prove_all_segments::( + &all_stark, + &config, + inputs, + max_cpu_len_log, + &mut timing, + None, + )?; + + timing.filter(Duration::from_millis(100)).print(); + + verify_all_proofs(&all_stark, &proofs, &config) +} + +fn giver_bytecode() -> Vec { + hex!("608060405234801561001057600080fd5b50600436106100365760003560e01c8063a52c101e1461003b578063fc0c546a14610050575b600080fd5b61004e61004936600461010c565b61007f565b005b600054610063906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b60005460405163a9059cbb60e01b8152731f9090aae28b8a3dceadf281b0f12828e676c3266004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156100e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101089190610125565b5050565b60006020828403121561011e57600080fd5b5035919050565b60006020828403121561013757600080fd5b8151801515811461014757600080fd5b939250505056fea264697066735822122050741efdbac11eb0bbb776ce3ac6004e596b7d7559658a12506164388c371cfd64736f6c63430008140033").into() +} + +fn token_bytecode() -> Vec { + hex!("608060405234801561001057600080fd5b50600436106100935760003560e01c8063313ce56711610066578063313ce567146100fe57806370a082311461010d57806395d89b4114610136578063a9059cbb1461013e578063dd62ed3e1461015157600080fd5b806306fdde0314610098578063095ea7b3146100b657806318160ddd146100d957806323b872dd146100eb575b600080fd5b6100a061018a565b6040516100ad919061056a565b60405180910390f35b6100c96100c43660046105d4565b61021c565b60405190151581526020016100ad565b6002545b6040519081526020016100ad565b6100c96100f93660046105fe565b610236565b604051601281526020016100ad565b6100dd61011b36600461063a565b6001600160a01b031660009081526020819052604090205490565b6100a061025a565b6100c961014c3660046105d4565b610269565b6100dd61015f36600461065c565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101999061068f565b80601f01602080910402602001604051908101604052809291908181526020018280546101c59061068f565b80156102125780601f106101e757610100808354040283529160200191610212565b820191906000526020600020905b8154815290600101906020018083116101f557829003601f168201915b5050505050905090565b60003361022a818585610277565b60019150505b92915050565b600033610244858285610289565b61024f85858561030c565b506001949350505050565b6060600480546101999061068f565b60003361022a81858561030c565b610284838383600161036b565b505050565b6001600160a01b03838116600090815260016020908152604080832093861683529290522054600019811461030657818110156102f757604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b6103068484848403600061036b565b50505050565b6001600160a01b03831661033657604051634b637e8f60e11b8152600060048201526024016102ee565b6001600160a01b0382166103605760405163ec442f0560e01b8152600060048201526024016102ee565b610284838383610440565b6001600160a01b0384166103955760405163e602df0560e01b8152600060048201526024016102ee565b6001600160a01b0383166103bf57604051634a1406b160e11b8152600060048201526024016102ee565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561030657826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161043291815260200190565b60405180910390a350505050565b6001600160a01b03831661046b57806002600082825461046091906106c9565b909155506104dd9050565b6001600160a01b038316600090815260208190526040902054818110156104be5760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016102ee565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b0382166104f957600280548290039055610518565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161055d91815260200190565b60405180910390a3505050565b600060208083528351808285015260005b818110156105975785810183015185820160400152820161057b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146105cf57600080fd5b919050565b600080604083850312156105e757600080fd5b6105f0836105b8565b946020939093013593505050565b60008060006060848603121561061357600080fd5b61061c846105b8565b925061062a602085016105b8565b9150604084013590509250925092565b60006020828403121561064c57600080fd5b610655826105b8565b9392505050565b6000806040838503121561066f57600080fd5b610678836105b8565b9150610686602084016105b8565b90509250929050565b600181811c908216806106a357607f821691505b6020821081036106c357634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561023057634e487b7160e01b600052601160045260246000fdfea2646970667358221220266a323ae4a816f6c6342a5be431fedcc0d45c44b02ea75f5474eb450b5d45b364736f6c63430008140033").into() +} + +fn giver_storage() -> HashMap { + let mut storage = HashMap::new(); + storage.insert( + U256::zero(), + sd2u("546584486846459126461364135121053344201067465379"), + ); + storage +} + +fn token_storage() -> HashMap { + let mut storage = HashMap::new(); + storage.insert( + sd2u("82183438603287090451672504949863617512989139203883434767553028632841710582583"), + sd2u("1000000000000000000000"), + ); + storage +} + +fn token_storage_after() -> HashMap { + let mut storage = HashMap::new(); + storage.insert( + sd2u("82183438603287090451672504949863617512989139203883434767553028632841710582583"), + sd2u("900000000000000000000"), + ); + storage.insert( + sd2u("53006154680716014998529145169423020330606407246856709517064848190396281160729"), + sd2u("100000000000000000000"), + ); + storage +} + +fn giver_account() -> AccountRlp { + let code = giver_bytecode(); + let len = code.len(); + AccountRlp { + nonce: 1.into(), + balance: 0.into(), + code_hash: H256::from_uint(&hash_bytecode_u256(code)), + code_length: len.into(), + } +} + +fn token_account() -> AccountRlp { + let code = token_bytecode(); + let len = code.len(); + AccountRlp { + nonce: 1.into(), + balance: 0.into(), + code_hash: H256::from_uint(&hash_bytecode_u256(code)), + code_length: len.into(), + } +} + +fn sender_account() -> AccountRlp { + AccountRlp { + nonce: 0.into(), + balance: sd2u("10000000000000000000000"), + ..Default::default() + } +} + +fn signed_tx() -> Vec { + hex!("02f88701800a0a830142c594e7f1725e7734ce288f8367e1bb143e90bb3f051280a4a52c101e0000000000000000000000000000000000000000000000056bc75e2d63100000c001a0303f5591159d7ea303faecb1c8bd8624b55732f769de28b111190dfb9a7c5234a019d5d6d38938dc1c63acbe106cf361672def773ace4ca587860117d057326627").into() +} + +fn bloom_bytes() -> [u8; 256] { + hex!("00000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000002000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000020000000000080000000000000000000000000000000000000000000000000000000000000000") +} + +fn bloom() -> [U256; 8] { + let bloom = bloom_bytes() + .chunks_exact(32) + .map(U256::from_big_endian) + .collect::>(); + bloom.try_into().unwrap() +} + +fn set_account( + smt: &mut Smt, + addr: Address, + account: &AccountRlp, + storage: &HashMap, +) { + smt.set(key_balance(addr), account.balance); + smt.set(key_nonce(addr), account.nonce); + smt.set(key_code(addr), h2u(account.code_hash)); + smt.set(key_code_length(addr), account.code_length); + for (&k, &v) in storage { + smt.set(key_storage(addr, k), v); + } +} From a2b39950eee2f259f9a5b99e889fc5f7343b76e5 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 2 Oct 2024 15:25:41 +0200 Subject: [PATCH 08/60] Add type accounts interface --- .../src/cpu/kernel/aggregator.rs | 3 + .../src/cpu/kernel/asm/balance.asm | 27 ++- .../src/cpu/kernel/asm/core/create.asm | 48 ++++-- .../asm/core/create_contract_account.asm | 157 ++++++++++++------ .../src/cpu/kernel/asm/core/nonce.asm | 100 +++++++---- .../src/cpu/kernel/asm/core/process_txn.asm | 4 +- .../src/cpu/kernel/asm/core/terminate.asm | 31 ++-- .../src/cpu/kernel/asm/core/util.asm | 61 +++++-- .../kernel/asm/journal/account_destroyed.asm | 68 +++++--- .../cpu/kernel/asm/journal/code_change.asm | 49 ++++-- .../cpu/kernel/asm/journal/nonce_change.asm | 35 ++-- .../cpu/kernel/asm/journal/storage_change.asm | 8 +- .../asm/linked_list/accounts_linked_list.asm | 11 +- .../asm/linked_list/state_linked_list.asm | 67 +++++++- .../src/cpu/kernel/asm/mpt/read.asm | 2 +- 15 files changed, 475 insertions(+), 196 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index e20fd6332..931153c46 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -47,7 +47,10 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/core/process_txn.asm"), include_str!("asm/core/syscall.asm"), include_str!("asm/core/terminate.asm"), + #[cfg(feature = "eth_mainnet")] include_str!("asm/core/transfer.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/core/transfer_cdk_erigon.asm"), include_str!("asm/core/util.asm"), include_str!("asm/core/access_lists.asm"), include_str!("asm/core/log.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/balance.asm b/evm_arithmetization/src/cpu/kernel/asm/balance.asm index d39f66063..971c317a1 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/balance.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/balance.asm @@ -26,16 +26,25 @@ global sys_balance: %endmacro global balance: - // stack: address, retdest - %mpt_read_state_trie - // stack: account_ptr, retdest - DUP1 ISZERO %jumpi(retzero) // If the account pointer is null, return 0. - %add_const(1) - // stack: balance_ptr, retdest - %mload_trie_data - // stack: balance, retdest + #[cfg(feature = "eth_mainnet")] + { + // stack: address, retdest + %mpt_read_state_trie + // stack: account_ptr, retdest + DUP1 ISZERO %jumpi(retzero) // If the account pointer is null, return 0. + %add_const(1) + // stack: balance_ptr, retdest + %mload_trie_data + // stack: balance, retdest + SWAP1 JUMP + } + #[cfg(feature = "cdk_erigon")] + { + // stack: address, retdest + %read_balance %mload_trie_data + // stack: balance, retdest SWAP1 JUMP - + } retzero: %stack (account_ptr, retdest) -> (retdest, 0) JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index 80f8f4618..12f084d4e 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -19,7 +19,7 @@ global sys_create: -> (sys_create_got_address, value, code_offset, code_len, kexit_info) %address // stack: sender, sys_create_got_address, value, code_offset, code_len, kexit_info - DUP1 %nonce + DUP1 %nonce_from_addr // stack: nonce, sender, sys_create_got_address, value, code_offset, code_len, kexit_info SWAP1 // stack: sender, nonce, sys_create_got_address, value, code_offset, code_len, kexit_info @@ -80,7 +80,7 @@ global create_common: DUP2 %selfbalance LT %jumpi(create_insufficient_balance) // Increment the sender's nonce. %address - DUP1 %nonce %eq_const(@MAX_NONCE) %jumpi(nonce_overflow) // EIP-2681 + DUP1 %nonce_from_addr %eq_const(@MAX_NONCE) %jumpi(nonce_overflow) // EIP-2681 %increment_nonce // stack: address, value, code_offset, code_len, kexit_info @@ -249,19 +249,37 @@ create_too_deep: // Pre stack: addr, codehash, redest // Post stack: (empty) global set_codehash: - // stack: addr, codehash, retdest - DUP1 %insert_touched_addresses - DUP1 %mpt_read_state_trie - // stack: account_ptr, addr, codehash, retdest - %add_const(3) - // stack: codehash_ptr, addr, codehash, retdest - DUP1 %mload_trie_data - // stack: prev_codehash, codehash_ptr, addr, codehash, retdest - DUP3 %journal_add_code_change // Add the code change to the journal. - %stack (codehash_ptr, addr, codehash) -> (codehash_ptr, codehash) - %mstore_trie_data - // stack: retdest - JUMP + #[cfg(feature = "eth_mainnet")] + { + // stack: addr, codehash, retdest + DUP1 %insert_touched_addresses + DUP1 %mpt_read_state_trie + // stack: account_ptr, addr, codehash, retdest + %add_const(3) + // stack: codehash_ptr, addr, codehash, retdest + DUP1 %mload_trie_data + // stack: prev_codehash, codehash_ptr, addr, codehash, retdest + DUP3 %journal_add_code_change // Add the code change to the journal. + %stack (codehash_ptr, addr, codehash) -> (codehash_ptr, codehash) + %mstore_trie_data + // stack: retdest + JUMP + } + #[cfg(feature = "cdk_erigon")] + { + // stack: addr, codehash, retdest + DUP1 %insert_touched_addresses + DUP1 %read_code %mload_trie_data + // stack: prev_codehash, addr, codehash, retdest + DUP2 %read_code_lenght %mload_trie_data + %stack (prev_code_length, prev_codehash, addr) -> (addr, prev_codehash, prev_code_length, addr) + %journal_add_code_change // Add the code change to the journal. + // stack: addr, codehash, retdest + DUP2 DUP2 %set_code + %returndatasize DUP2 %set_code_length + // stack: addr, codehash, retdest + %pop2 JUMP + } // Check and charge gas cost for initcode size. See EIP-3860. // Pre stack: code_size, kexit_info diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm index a614f9fa8..272d2c460 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm @@ -5,64 +5,113 @@ // stack: address DUP1 %insert_touched_addresses DUP1 %append_created_contracts - DUP1 %mpt_read_state_trie - // stack: existing_account_ptr, address - // If the account doesn't exist, there's no need to check its balance or nonce, - // so we can skip ahead, setting existing_balance = existing_account_ptr = 0. - DUP1 ISZERO %jumpi(%%add_account) + #[cfg(feature = "eth_mainnet")] + { + %mpt_read_state_trie - // Check that the nonce is 0. - // stack: existing_account_ptr, address - DUP1 %mload_trie_data // nonce = account[0] - // stack: nonce, existing_account_ptr, address - %jumpi(%%error_collision) - // stack: existing_account_ptr, address - // Check that the code is empty. - %add_const(3) - // stack: existing_codehash_ptr, address - DUP1 %mload_trie_data // codehash = account[3] - %eq_const(@EMPTY_STRING_HASH) ISZERO %jumpi(%%error_collision) - // stack: existing_codehash_ptr, address - %sub_const(2) %mload_trie_data // balance = account[1] - %jump(%%do_insert) + // If the account doesn't exist, there's no need to check its balance or nonce, + // so we can skip ahead, setting existing_balance = existing_account_ptr = 0. + DUP1 ISZERO %jumpi(%%add_account) + + DUP1 %mload_trie_data// nonce = account[0] + // stack: nonce, existing_account_ptr, address + %jumpi(%%error_collision) + // stack: existing_account_ptr, address + // Check that the code is empty. + %add_const(3) + // stack: existing_codehash_ptr, address + DUP1 %mload_trie_data // codehash = account[3] + %eq_const(@EMPTY_STRING_HASH) ISZERO %jumpi(%%error_collision) + // stack: existing_codehash_ptr, address + %sub_const(2) %mload_trie_data // balance = account[1] + %jump(%%do_insert) -%%add_account: - // stack: existing_balance, address - DUP2 PUSH 1 - // stack: is_contract, address, existing_balance, address - %journal_add_account_created -%%do_insert: - // stack: new_acct_value=existing_balance, address - // Write the new account's data to MPT data, and get a pointer to it. - %get_trie_data_size - // stack: account_ptr, new_acct_value, address - PUSH 0 DUP4 %journal_add_nonce_change - PUSH 1 %append_to_trie_data // nonce = 1 - // stack: account_ptr, new_acct_value, address - SWAP1 %append_to_trie_data // balance = new_acct_value - // stack: account_ptr, address - PUSH 0 %append_to_trie_data // storage_root = nil - // stack: account_ptr, address - PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') - // stack: account_ptr, address - SWAP1 - // stack: address, account_ptr - %addr_to_state_key - // stack: state_key, account_ptr - %mpt_insert_state_trie - // stack: (empty) - PUSH 0 // success - %jump(%%end) + %%add_account: + // stack: existing_balance, address + DUP2 PUSH 1 + // stack: is_contract, address, existing_balance, address + %journal_add_account_created + %%do_insert: + // stack: new_acct_value=existing_balance, address + // Write the new account's data to MPT data, and get a pointer to it. + %get_trie_data_size + // stack: account_ptr, new_acct_value, address + PUSH 0 DUP4 %journal_add_nonce_change + PUSH 1 %append_to_trie_data // nonce = 1 + // stack: account_ptr, new_acct_value, address + SWAP1 %append_to_trie_data // balance = new_acct_value + // stack: account_ptr, address + PUSH 0 %append_to_trie_data // storage_root = nil + // stack: account_ptr, address + PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') + // stack: account_ptr, address + SWAP1 + // stack: address, account_ptr + %addr_to_state_key + // stack: state_key, account_ptr + %mpt_insert_state_trie + // stack: (empty) + PUSH 0 // success + %jump(%%end) -// If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. -// (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) -// So we return 1 to indicate an error. -%%error_collision: - %stack (existing_account_ptr, address) -> (1) + // If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. + // (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) + // So we return 1 to indicate an error. + %%error_collision: + %stack (existing_account_ptr, address) -> (1) -%%end: - // stack: status -%endmacro + %%end: + // stack: status + %endmacro + } + #[cfg(feature = "cdk_erigon")] + { + POP + %read_code ISZERO %jumpi(%%add_account) + // Check that the nonce is 0. + // stack: address + DUP1 %nonce + // stack: nonce, address + %jumpi(%%error_collision) + // stack: address + // Check that the code is empty. + DUP1 %extcodehash + %eq_const(@EMPTY_STRING_POSEIDON_HASH) ISZERO %jumpi(%%error_collision) + DUP1 %balance + %jump(%%do_insert) + + %%add_account: + // stack: address + DUP1 PUSH 1 + // stack: is_contract, address, address + %journal_add_account_created + // stack: address + PUSH 0 + %%do_insert: + // stack: new_acct_value, address + // Write the new account's data to MPT data, and get a pointer to it. + // stack: new_acct_value, address + PUSH 0 DUP3 %journal_add_nonce_change + %stack (new_acct_value, address) -> (address, 1, new_acct_value, address) + %set_nonce // nonce = 1 + // stack: new_acct_value, address + DUP2 %set_balance // balance = new_acct_value + %stack (address) -> (address, @EMPTY_STRING_POSEIDON_HASH) + %set_code + // stack: empty + PUSH 0 // success + %jump(%%end) + + // If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. + // (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) + // So we return 1 to indicate an error. + %%error_collision: + %stack (address) -> (1) + + %%end: + // stack: status + %endmacro + } %macro append_created_contracts // stack: address diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm index 48486be9e..c923f9598 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm @@ -2,15 +2,25 @@ // Pre stack: address, retdest // Post stack: (empty) global nonce: - // stack: address, retdest - %mpt_read_state_trie - // stack: account_ptr, retdest - // The nonce is the first account field, so we deref the account pointer itself. - // Note: We don't need to handle account_ptr=0, as trie_data[0] = 0, - // so the deref will give 0 (the default nonce) as desired. - %mload_trie_data - // stack: nonce, retdest - SWAP1 JUMP + #[cfg(feature = "eth_mainnet")] + { + // stack: address, retdest + %mpt_read_state_trie + // stack: account_ptr, retdest + // The nonce is the first account field, so we deref the account pointer itself. + // Note: We don't need to handle account_ptr=0, as trie_data[0] = 0, + // so the deref will give 0 (the default nonce) as desired. + %mload_trie_data + // stack: nonce, retdest + SWAP1 JUMP + } + #[cfg(feature = "cdk_erigon")] + { + // stack: address, retdest + %read_nonce %mload_trie_data + // stack: nonce, retdest + SWAP1 JUMP + } // Convenience macro to call nonce and return where we left off. %macro nonce @@ -21,25 +31,59 @@ global nonce: // Increment the given account's nonce. Assumes the account already exists; panics otherwise. global increment_nonce: - // stack: address, retdest - DUP1 - %mpt_read_state_trie - // stack: account_ptr, address, retdest - DUP1 ISZERO %jumpi(increment_nonce_no_such_account) - // stack: nonce_ptr, address, retdest - DUP1 %mload_trie_data - // stack: nonce, nonce_ptr, address, retdest - DUP1 DUP4 %journal_add_nonce_change - // stack: nonce, nonce_ptr, address, retdest - %increment - SWAP1 - // stack: nonce_ptr, nonce', address, retdest - %mstore_trie_data - // stack: address, retdest - POP - JUMP -global increment_nonce_no_such_account: - PANIC + #[cfg(feature = "eth_mainnet")] + { + // stack: address, retdest + DUP1 + %mpt_read_state_trie + // stack: account_ptr, address, retdest + DUP1 ISZERO %jumpi(increment_nonce_no_such_account) + // stack: nonce_ptr, address, retdest + DUP1 %mload_trie_data + // stack: nonce, nonce_ptr, address, retdest + DUP1 DUP4 %journal_add_nonce_change + // stack: nonce, nonce_ptr, address, retdest + %increment + SWAP1 + // stack: nonce_ptr, nonce', address, retdest + %mstore_trie_data + // stack: address, retdest + POP + JUMP + global increment_nonce_no_such_account: + PANIC + } + #[cfg(feature = "cdk_erigon")] + { + // stack: address, retdest + DUP1 + %read_nonce + // stack: nonce_ptr, address, retdest + DUP1 ISZERO %jumpi(create_nonce) + // stack: nonce_ptr, address, retdest + DUP1 %mload_trie_data + // stack: nonce, nonce_ptr, address, retdest + DUP1 DUP4 %journal_add_nonce_change + // stack: nonce, nonce_ptr, address, retdest + %increment + SWAP1 + // stack: nonce_ptr, nonce', address, retdest + %mstore_trie_data + // stack: address, retdest + POP + JUMP + + create_nonce: + // stack: nonce_ptr, address, retdest + POP + // stack: address, retdest + PUSH 0 DUP2 %journal_add_nonce_change + // stack: address, retdest + PUSH 1 + SWAP1 + %set_nonce + } + // Convenience macro to call increment_nonce and return where we left off. %macro increment_nonce diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 6a006ef71..0b9c9b19f 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -27,7 +27,7 @@ global process_normalized_txn: // stack: sender, retdest // Check that txn nonce matches account nonce. - DUP1 %nonce + DUP1 %nonce_from_addr DUP1 %eq_const(@MAX_NONCE) %assert_zero(invalid_txn_2) // EIP-2681 // stack: sender_nonce, sender, retdest %mload_txn_field(@TXN_FIELD_NONCE) @@ -117,7 +117,7 @@ global process_contract_creation_txn: %mload_txn_field(@TXN_FIELD_ORIGIN) // stack: origin, retdest - DUP1 %nonce + DUP1 %nonce_from_addr // stack: origin_nonce, origin, retdest %decrement // Need the non-incremented nonce SWAP1 diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm b/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm index 1d406097c..3a01a787a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm @@ -86,16 +86,27 @@ global sys_selfdestruct: %stack (kexit_info, balance, address, recipient) -> (balance, address, recipient, kexit_info) // Set the balance of the address to 0. - // stack: balance, address, recipient, kexit_info - PUSH 0 - // stack: 0, balance, address, recipient, kexit_info - DUP3 %mpt_read_state_trie - // stack: account_ptr, 0, balance, address, recipient, kexit_info - %add_const(1) - // stack: balance_ptr, 0, balance, address, recipient, kexit_info - %mstore_trie_data - - + #[cfg(feature = "eth_mainnet")] + { + // stack: balance, address, recipient, kexit_info + PUSH 0 + // stack: 0, balance, address, recipient, kexit_info + DUP3 %mpt_read_state_trie + // stack: account_ptr, 0, balance, address, recipient, kexit_info + %add_const(1) + // stack: balance_ptr, 0, balance, address, recipient, kexit_info + %mstore_trie_data + } + #[cfg(feature = "cdk_erigon")] + { + // Set the balance of the address to 0. + // stack: balance, address, recipient, kexit_info + DUP1 ISZERO %jumpi(selfdestruct_balance_is_zero) + DUP2 %remove_balance + // stack: balance, address, recipient, kexit_info + } + +selfdestruct_balance_is_zero: // EIP-6780: insert address into the selfdestruct set only if contract has been created // during the current transaction. // stack: balance, address, recipient, kexit_info diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index 713b2274f..b81fef215 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -57,27 +57,54 @@ // Returns 1 if the account is non-existent, 0 otherwise. %macro is_non_existent // stack: addr - %mpt_read_state_trie ISZERO + #[cfg(feature = "eth_mainnet")] + { + %mpt_read_state_trie ISZERO + } + #[cfg(feature = "cdk_erigon")] + { + %key_code %search_key ISZERO + } %endmacro + // Returns 1 if the account is empty, 0 otherwise. %macro is_empty - // stack: addr - %mpt_read_state_trie - // stack: account_ptr - DUP1 ISZERO %jumpi(%%false) - // stack: account_ptr - DUP1 %mload_trie_data - // stack: nonce, account_ptr - ISZERO %not_bit %jumpi(%%false) - %increment DUP1 %mload_trie_data - // stack: balance, balance_ptr - ISZERO %not_bit %jumpi(%%false) - %add_const(2) %mload_trie_data - // stack: code_hash - PUSH @EMPTY_STRING_HASH - EQ - %jump(%%after) + #[cfg(feature = "eth_mainnet")] + { + // stack: addr + %mpt_read_state_trie + // stack: account_ptr + DUP1 ISZERO %jumpi(%%false) + // stack: account_ptr + DUP1 %mload_trie_data + // stack: nonce, account_ptr + ISZERO %not_bit %jumpi(%%false) + %increment DUP1 %mload_trie_data + // stack: balance, balance_ptr + ISZERO %not_bit %jumpi(%%false) + %add_const(2) %mload_trie_data + // stack: code_hash + PUSH @EMPTY_STRING_HASH + EQ + %jump(%%after) + } + #[cfg(feature = "cdk_erigon")] + { + // stack: addr + DUP1 %read_nonce %mload_trie_data + // stack: nonce, addr + ISZERO %not_bit %jumpi(%%false) + // stack: addr + DUP1 %read_balance %mload_trie_data + // stack: balance, addr + ISZERO %not_bit %jumpi(%%false) + // stack: addr + %read_code %mload_trie_data + // stack: codehash + %eq_const(@EMPTY_STRING_POSEIDON_HASH) + %jump(%%after) + } %%false: // stack: account_ptr POP 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 d62f3d422..2d8fafde4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm @@ -12,27 +12,47 @@ global revert_account_destroyed: PUSH revert_account_destroyed_contd DUP2 %jump(remove_selfdestruct_list) revert_account_destroyed_contd: - // stack: address, target, prev_balance, retdest - SWAP1 - // Remove `prev_balance` from `target`'s balance. - // stack: target, address, prev_balance, retdest - %read_accounts_linked_list - // stack: target_payload_ptr, address, prev_balance, retdest - DUP1 - %assert_nonzero - %add_const(1) - // stack: target_balance_ptr, address, prev_balance, retdest - DUP3 - DUP2 %mload_trie_data - // stack: target_balance, prev_balance, target_balance_ptr, address, prev_balance, retdest - SUB SWAP1 %mstore_trie_data - // Set `address`'s balance to `prev_balance`. - // stack: address, prev_balance, retdest - %read_accounts_linked_list - // stack: account_payload_ptr, prev_balance, retdest - DUP1 - %assert_nonzero - %increment - // stack: account_balance_payload_ptr, prev_balance, retdest - %mstore_trie_data - JUMP + #[cfg(feature = "eth_mainnet")] + { + // stack: address, target, prev_balance, retdest + SWAP1 + // Remove `prev_balance` from `target`'s balance. + // stack: target, address, prev_balance, retdest + %read_account_from_addr + // stack: target_payload_ptr, address, prev_balance, retdest + DUP1 + %assert_nonzero + %add_const(1) + // stack: target_balance_ptr, address, prev_balance, retdest + DUP3 + DUP2 %mload_trie_data + // stack: target_balance, prev_balance, target_balance_ptr, address, prev_balance, retdest + SUB SWAP1 %mstore_trie_data + // Set `address`'s balance to `prev_balance`. + // stack: address, prev_balance, retdest + %read_account_from_addr + // stack: account_payload_ptr, prev_balance, retdest + DUP1 + %assert_nonzero + %increment + // stack: account_balance_payload_ptr, prev_balance, retdest + %mstore_trie_data + JUMP + } + #[cfg(feature = "cdk_erigon")] + { + // stack: address, target, prev_balance, retdest + SWAP1 + // Remove `prev_balance` from `target`'s balance. + // stack: target, address, prev_balance, retdest + %key_balance DUP1 %read_key %mload_trie_data + // stack: target_balance, target_balance_key, address, prev_balance, retdest + %stack (target_balance, target_balance_key, address, prev_balance) -> (target_balance, prev_balance, target_balance_key, address, prev_balance) + // stack: target_balance, prev_balance, target_balance_key, address, prev_balance, retdest + SUB SWAP1 %insert_key + // Set `address`'s balance to `prev_balance`. + // stack: address, prev_balance, retdest + %set_balance + // stack: retdest + JUMP + } \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm index 0fc33f9dd..11fecefce 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm @@ -1,20 +1,41 @@ // struct CodeChange { address, prev_codehash } %macro journal_add_code_change - %journal_add_2(@JOURNAL_ENTRY_CODE_CHANGE) + #[cfg(feature = "eth_mainnet")] + { + %journal_add_2(@JOURNAL_ENTRY_CODE_CHANGE) + } + #[cfg(feature) + "cdk_erigon"] + { + %journal_add_3(@JOURNAL_ENTRY_CODE_CHANGE) + } %endmacro global revert_code_change: - // stack: entry_ptr, ptr, retdest - POP - %journal_load_2 - // stack: address, prev_codehash, retdest - %read_accounts_linked_list - // stack: account_ptr, prev_codehash, retdest - DUP1 %assert_nonzero - // stack: account_ptr, prev_codehash, retdest - %add_const(3) - // stack: codehash_ptr, prev_codehash, retdest - %mstore_trie_data - // stack: retdest - JUMP + #[cfg(feature = "eth_mainnet")] + { + // stack: entry_ptr, ptr, retdest + POP + %journal_load_2 + // stack: address, prev_codehash, retdest + %read_account_from_addr + // stack: account_ptr, prev_codehash, retdest + DUP1 %assert_nonzero + // stack: account_ptr, prev_codehash, retdest + %add_const(3) + // stack: codehash_ptr, prev_codehash, retdest + %mstore_trie_data + // stack: retdest + JUMP + } + #[cfg(feature = "cdk_erigon")] + { + // stack: entry_ptr, ptr, retdest + POP + %journal_load_3 + %stack (address, prev_codehash, prev_code_length) -> (address, prev_codehash, address, prev_code_length) + %set_code + %set_code_length + // stack: retdest + 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 0c1198e52..0c8947554 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm @@ -5,14 +5,27 @@ %endmacro global revert_nonce_change: - // stack: entry_type, ptr, retdest - POP - %journal_load_2 - // stack: address, prev_nonce, retdest - %read_accounts_linked_list - // stack: payload_ptr, prev_nonce, retdest - DUP1 %assert_nonzero - // stack: nonce_ptr, prev_nonce, retdest - %mstore_trie_data - // stack: retdest - JUMP + #[cfg(feature = "eth_mainnet")] + { + // stack: entry_type, ptr, retdest + POP + %journal_load_2 + // stack: address, prev_nonce, retdest + %read_account_from_addr + // stack: payload_ptr, prev_nonce, retdest + DUP1 %assert_nonzero + // stack: nonce_ptr, prev_nonce, retdest + %mstore_trie_data + // stack: retdest + JUMP + } + #[cfg(feature = "cdk_erigon")] + { + // stack: entry_type, ptr, retdest + POP + %journal_load_2 + // stack: address, prev_nonce, retdest + %set_nonce + // stack: retdest + JUMP + } diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm index 0b1cb0972..3fd20ee19 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm @@ -16,10 +16,8 @@ global revert_storage_change: delete: // stack: address, slot, prev_value, retdest - SWAP2 POP - // stack: slot, address, retdest - %slot_to_storage_key - SWAP1 %addr_to_state_key - // stack: addr_key, slot_key, retdest + %addr_to_state_key + // stack: addr_key, slot, prev_value, retdest %remove_slot_from_addr_key + POP JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm index d5e89f18a..3c9416c91 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm @@ -378,7 +378,7 @@ remove_all_slots_end: %%after: %endmacro -%macro read_accounts_linked_list +%macro read_account_from_addr %stack (addr) -> (addr, %%after) %addr_to_state_key %jump(search_account) @@ -386,6 +386,15 @@ remove_all_slots_end: // stack: account_ptr %endmacro +%macro nonce_from_ptr: + %mload_trie_data +%endmacro + +%macro balance_from_ptr: + %increment + %mload_trie_data +%endmacro + %macro first_account // stack: empty PUSH @SEGMENT_ACCOUNTS_LINKED_LIST diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm index 7d7301275..bfd33df6b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm @@ -125,12 +125,40 @@ store_state_slots_end: %mul_const(4) %endmacro +%macro set_nonce + // stack: address, nonce + %key_nonce + %insert_key + // stack: (empty) +%endmacro + +%macro set_balance + // stack: address, balance + %key_balance + %insert_key + // stack: (empty) +%endmacro + +%macro set_code + // stack: address, code + %key_code + %insert_key + // stack: (empty) +%endmacro + +%macro set_code_length + // stack: address, code_lenght + %key_code_lenght + %insert_key + // stack: (empty) +%endmacro + + %macro insert_slot // stack: addr, slot, value %addr_to_state_key %key_storage %insert_key -%%after: // stack: (empty) %endmacro @@ -138,7 +166,6 @@ store_state_slots_end: // stack: addr_key, slot_key, value %key_storage %insert_key -%%after: // stack: (empty) %endmacro @@ -291,19 +318,44 @@ key_not_found: JUMP %macro search_key - // stack: state_key, storage_key, ptr - %stack (key, ptr) -> (key, ptr, %%after) + %stack (key) -> (key, %%after) %jump(search_key) %%after: // stack: value %endmacro - %macro search_slot_from_addr_key // stack: addr_key, slot %key_storage %search_key %endmacro +%macro read_balance: + // stack: addr_key + %key_balance + %search_key +%endmacro + +%macro read_code + // stack: addr_key + %key_code + %search_key + // stack: code_hash +%endmacro + +%macro read_code_lenght + // stack: addr_key + %key_code_length + %search_key + // stack: code_length +%endmacro + +%macro read_nonce + // stack: addr_key + %key_nonce + %search_key + // stack: nonce +%endmacro + %macro remove_key PUSH %%after SWAP1 @@ -311,6 +363,11 @@ key_not_found: %%after: %endmacro +%macro remove_balance + %key_balance + %remove_key +%endmacro + %macro remove_slot_from_addr_key %key_storage %remove_key diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm index 303377c04..0c683c7d9 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm @@ -3,7 +3,7 @@ // trie_data segment. Return null if the address is not found. global mpt_read_state_trie: // stack: addr, retdest - %read_accounts_linked_list + %read_account_from_addr // stack: account_ptr, retdest SWAP1 // stack: retdest, account_ptr From 7cd4270fe378ba356c677db871b5c33e5d43f3ff Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 2 Oct 2024 17:22:02 +0200 Subject: [PATCH 09/60] Missing file --- .../src/cpu/kernel/aggregator.rs | 4 +- .../src/cpu/kernel/asm/balance.asm | 4 +- .../src/cpu/kernel/asm/core/create.asm | 4 +- .../asm/core/create_contract_account.asm | 7 +- .../src/cpu/kernel/asm/core/nonce.asm | 8 +- .../src/cpu/kernel/asm/core/terminate.asm | 4 +- .../kernel/asm/core/transfer_cdk_erigon.asm | 119 ++++++++++++++++++ .../src/cpu/kernel/asm/core/util.asm | 8 +- .../kernel/asm/journal/account_destroyed.asm | 4 +- .../cpu/kernel/asm/journal/code_change.asm | 8 +- .../cpu/kernel/asm/journal/nonce_change.asm | 4 +- .../asm/linked_list/state_linked_list.asm | 2 +- 12 files changed, 148 insertions(+), 28 deletions(-) create mode 100644 evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index 931153c46..b41340400 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 155 + 156 } else { // unreachable 0 @@ -164,6 +164,8 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/shift.asm"), include_str!("asm/signed.asm"), #[cfg(feature = "cdk_erigon")] + include_str!("asm/smt/keys.asm"), + #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/utils.asm"), include_str!("asm/journal/journal.asm"), include_str!("asm/journal/account_loaded.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/balance.asm b/evm_arithmetization/src/cpu/kernel/asm/balance.asm index 971c317a1..32e8e84ec 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/balance.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/balance.asm @@ -26,7 +26,7 @@ global sys_balance: %endmacro global balance: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: address, retdest %mpt_read_state_trie @@ -38,7 +38,7 @@ global balance: // stack: balance, retdest SWAP1 JUMP } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: address, retdest %read_balance %mload_trie_data diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index 12f084d4e..5f469b7e0 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -249,7 +249,7 @@ create_too_deep: // Pre stack: addr, codehash, redest // Post stack: (empty) global set_codehash: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: addr, codehash, retdest DUP1 %insert_touched_addresses @@ -265,7 +265,7 @@ global set_codehash: // stack: retdest JUMP } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: addr, codehash, retdest DUP1 %insert_touched_addresses diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm index 272d2c460..180839448 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm @@ -5,7 +5,7 @@ // stack: address DUP1 %insert_touched_addresses DUP1 %append_created_contracts - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { %mpt_read_state_trie @@ -62,9 +62,8 @@ %%end: // stack: status - %endmacro } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { POP %read_code ISZERO %jumpi(%%add_account) @@ -110,8 +109,8 @@ %%end: // stack: status - %endmacro } +%endmacro %macro append_created_contracts // stack: address diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm index c923f9598..93085e97d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm @@ -2,7 +2,7 @@ // Pre stack: address, retdest // Post stack: (empty) global nonce: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: address, retdest %mpt_read_state_trie @@ -14,7 +14,7 @@ global nonce: // stack: nonce, retdest SWAP1 JUMP } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: address, retdest %read_nonce %mload_trie_data @@ -31,7 +31,7 @@ global nonce: // Increment the given account's nonce. Assumes the account already exists; panics otherwise. global increment_nonce: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: address, retdest DUP1 @@ -53,7 +53,7 @@ global increment_nonce: global increment_nonce_no_such_account: PANIC } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: address, retdest DUP1 diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm b/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm index 3a01a787a..e3f5f0405 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm @@ -86,7 +86,7 @@ global sys_selfdestruct: %stack (kexit_info, balance, address, recipient) -> (balance, address, recipient, kexit_info) // Set the balance of the address to 0. - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: balance, address, recipient, kexit_info PUSH 0 @@ -97,7 +97,7 @@ global sys_selfdestruct: // stack: balance_ptr, 0, balance, address, recipient, kexit_info %mstore_trie_data } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // Set the balance of the address to 0. // stack: balance, address, recipient, kexit_info diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm b/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm new file mode 100644 index 000000000..be7b26add --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm @@ -0,0 +1,119 @@ +// Transfers some ETH from one address to another. The amount is given in wei. +// Pre stack: from, to, amount, retdest +// Post stack: status (0 indicates success) +global transfer_eth: + // stack: from, to, amount, retdest + %stack (from, to, amount, retdest) + -> (from, amount, to, amount, retdest) + %deduct_eth + // stack: deduct_eth_status, to, amount, retdest + %jumpi(transfer_eth_failure) + // stack: to, amount, retdest + %add_eth + %stack (retdest) -> (retdest, 0) + JUMP +global transfer_eth_failure: + %stack (to, amount, retdest) -> (retdest, 1) + JUMP + +// Convenience macro to call transfer_eth and return where we left off. +%macro transfer_eth + %stack (from, to, amount) -> (from, to, amount, %%after) + %jump(transfer_eth) +%%after: +%endmacro + +// Returns 0 on success, or 1 if addr has insufficient balance. Panics if addr isn't found in the trie. +// Pre stack: addr, amount, retdest +// Post stack: status (0 indicates success) +global deduct_eth: + // stack: addr, amount, retdest + DUP1 %insert_touched_addresses + DUP2 ISZERO %jumpi(deduct_eth_noop) + DUP1 %read_balance + // stack: balance_ptr, addr, amount, retdest + DUP1 %mload_trie_data + // stack: balance, balance_ptr, addr, amount, retdest + DUP1 DUP5 GT + // stack: amount > balance, balance, balance_ptr, addr, amount, retdest + %jumpi(deduct_eth_insufficient_balance) + // stack: balance, balance_ptr, addr, amount, retdest + DUP1 DUP5 EQ + // stack: amount == balance, balance, balance_ptr, addr, amount, retdest + %jumpi(deduct_eth_delete_balance) + %stack (balance, balance_ptr, addr, amount, retdest) -> (balance, amount, balance_ptr, retdest, 0) + SUB + SWAP1 + // stack: balance_ptr, balance - amount, retdest, 0 + %mstore_trie_data + // stack: retdest, 0 + JUMP +deduct_eth_insufficient_balance: + %stack (balance, balance_ptr, addr, amount, retdest) -> (retdest, 1) + JUMP +deduct_eth_delete_balance: + %stack (balance, balance_ptr, addr, amount, retdest) -> (addr, retdest, 0) + %remove_balanace + // stack: retdest, 0 + JUMP +deduct_eth_noop: + %stack (addr, amount, retdest) -> (retdest, 0) + JUMP + +// Convenience macro to call deduct_eth and return where we left off. +%macro deduct_eth + %stack (addr, amount) -> (addr, amount, %%after) + %jump(deduct_eth) +%%after: +%endmacro + +// Pre stack: addr, amount, redest +// Post stack: (empty) +global add_eth: + // stack: addr, amount, retdest + DUP1 %insert_touched_addresses + DUP2 ISZERO %jumpi(add_eth_noop) + // stack: addr, amount, retdest + DUP1 %read_code %mload_trie_data + // stack: codehash, addr, amount, retdest + ISZERO %jumpi(add_eth_new_account) // If the account is empty, we need to create the account. + // stack: addr, amount, retdest + %key_balance DUP1 %read_key // TODO: replace with read_balance? + DUP1 ISZERO %jumpi(add_eth_zero_balance) + %stack (balance_ptr, key_balance, amount) -> (balance_ptr, amount, balance_ptr) + // stack: balance_ptr, amount, balance_ptr, retdest + %mload_trie_data ADD + // stack: balance+amount, balance_ptr, retdest + SWAP1 %mstore_trie_data + JUMP +add_eth_zero_balance: + // stack: balance_ptr, key_balance, amount, retdest + POP + // stack: key_balance, amount, retdest + %insert_key // TODO: replace with set_balance? + // stack: retdest + JUMP + +global add_eth_new_account: + // stack: addr, amount, retdest + DUP1 PUSH 0 + // stack: is_eoa, addr, amount, retdest + %journal_add_account_created + // stack: addr, amount, retdest + DUP1 %key_code + %stack (key_code) -> (key_code, @EMPTY_STRING_POSEIDON_HASH) + %insert_key // TODO: replace with set_code? + // stack: addr, amount, retdest + %set_balance + JUMP + +add_eth_noop: + // stack: addr, amount, retdest + %pop2 JUMP + +// Convenience macro to call add_eth and return where we left off. +%macro add_eth + %stack (addr, amount) -> (addr, amount, %%after) + %jump(add_eth) +%%after: +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index b81fef215..174d9bf0e 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -57,11 +57,11 @@ // Returns 1 if the account is non-existent, 0 otherwise. %macro is_non_existent // stack: addr - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { %mpt_read_state_trie ISZERO } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { %key_code %search_key ISZERO } @@ -70,7 +70,7 @@ // Returns 1 if the account is empty, 0 otherwise. %macro is_empty - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: addr %mpt_read_state_trie @@ -89,7 +89,7 @@ EQ %jump(%%after) } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: addr DUP1 %read_nonce %mload_trie_data 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 2d8fafde4..59676b4ad 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm @@ -12,7 +12,7 @@ global revert_account_destroyed: PUSH revert_account_destroyed_contd DUP2 %jump(remove_selfdestruct_list) revert_account_destroyed_contd: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: address, target, prev_balance, retdest SWAP1 @@ -39,7 +39,7 @@ revert_account_destroyed_contd: %mstore_trie_data JUMP } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: address, target, prev_balance, retdest SWAP1 diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm index 11fecefce..6ba5d29df 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm @@ -1,18 +1,18 @@ // struct CodeChange { address, prev_codehash } %macro journal_add_code_change - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { %journal_add_2(@JOURNAL_ENTRY_CODE_CHANGE) } - #[cfg(feature) + "cdk_erigon"] + #[cfg(feature = cdk_erigon)] { %journal_add_3(@JOURNAL_ENTRY_CODE_CHANGE) } %endmacro global revert_code_change: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: entry_ptr, ptr, retdest POP @@ -28,7 +28,7 @@ global revert_code_change: // stack: retdest JUMP } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: entry_ptr, ptr, retdest POP 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 0c8947554..c5d1f535c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm @@ -5,7 +5,7 @@ %endmacro global revert_nonce_change: - #[cfg(feature = "eth_mainnet")] + #[cfg(feature = eth_mainnet)] { // stack: entry_type, ptr, retdest POP @@ -19,7 +19,7 @@ global revert_nonce_change: // stack: retdest JUMP } - #[cfg(feature = "cdk_erigon")] + #[cfg(feature = cdk_erigon)] { // stack: entry_type, ptr, retdest POP diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm index bfd33df6b..385c9c0c1 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm @@ -329,7 +329,7 @@ key_not_found: %search_key %endmacro -%macro read_balance: +%macro read_balance // stack: addr_key %key_balance %search_key From 4eb61757222a58b0008d36c1f1f0fe87c636f999 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 3 Oct 2024 18:27:39 +0200 Subject: [PATCH 10/60] Add initial and final smt --- .../src/cpu/kernel/aggregator.rs | 17 +- .../src/cpu/kernel/asm/account_code.asm | 29 +- .../src/cpu/kernel/asm/core/create.asm | 6 +- .../asm/core/create_contract_account.asm | 150 ++---- .../src/cpu/kernel/asm/core/process_txn.asm | 4 +- .../kernel/asm/core/transfer_cdk_erigon.asm | 4 +- .../src/cpu/kernel/asm/core/util.asm | 53 +- .../kernel/asm/journal/account_destroyed.asm | 2 +- .../asm/linked_list/state_linked_list.asm | 462 ------------------ .../src/cpu/kernel/asm/main.asm | 11 +- .../src/cpu/kernel/asm/mpt/delete/delete.asm | 31 +- .../asm/mpt/insert/insert_trie_specific.asm | 23 +- .../src/cpu/kernel/asm/mpt/read.asm | 29 +- .../kernel/asm/mpt/storage/storage_write.asm | 39 ++ .../src/cpu/kernel/asm/smt/delete.asm | 20 +- .../src/cpu/kernel/assembler.rs | 2 +- .../cpu/kernel/constants/global_metadata.rs | 7 +- .../src/cpu/kernel/constants/mod.rs | 25 +- evm_arithmetization/src/cpu/kernel/opcodes.rs | 2 + evm_arithmetization/src/memory/segments.rs | 7 +- 20 files changed, 273 insertions(+), 650 deletions(-) delete mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index b41340400..ce1928cfd 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 156 + 157 } else { // unreachable 0 @@ -36,7 +36,10 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/core/call_gas.asm"), include_str!("asm/core/create.asm"), include_str!("asm/core/create_addresses.asm"), + #[cfg(feature = "eth_mainnet")] include_str!("asm/core/create_contract_account.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/core/create_type2_contract_account.asm"), include_str!("asm/core/exception.asm"), include_str!("asm/core/create_receipt.asm"), include_str!("asm/core/gas.asm"), @@ -127,10 +130,16 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/linked_list/accounts_linked_list.asm"), #[cfg(feature = "eth_mainnet")] include_str!("asm/linked_list/storage_linked_list.asm"), - #[cfg(feature = "cdk_erigon")] - include_str!("asm/linked_list/state_linked_list.asm"), + #[cfg(feature = "eth_mainnet")] include_str!("asm/linked_list/final_tries.asm"), + #[cfg(feature = "eth_mainnet")] include_str!("asm/linked_list/initial_tries.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/linked_list/type2/state_linked_list.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/linked_list/type2/final_tries.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/linked_list/type2/initial_tries.asm"), include_str!("asm/memory/core.asm"), include_str!("asm/memory/memcpy.asm"), include_str!("asm/memory/memset.asm"), @@ -167,6 +176,8 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/smt/keys.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/utils.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/smt/delete.asm"), include_str!("asm/journal/journal.asm"), include_str!("asm/journal/account_loaded.asm"), include_str!("asm/journal/account_destroyed.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 62b5b968b..8853e953a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -22,19 +22,30 @@ extcodehash_dead: %stack (address, kexit_info) -> (kexit_info, 0) EXIT_KERNEL +#[cfg(feature = eth_mainnet)] +{ +global extcodehash: + // stack: address, retdest + %mpt_read_state_trie + // stack: account_ptr, retdest + DUP1 ISZERO %jumpi(retzero) + %add_const(3) + // stack: codehash_ptr, retdest + %mload_trie_data + // stack: codehash, retdest + SWAP1 JUMP + retzero: + %stack (account_ptr, retdest) -> (retdest, 0) + JUMP +} +#[cfg(feature = cdk_erigon)] +{ global extcodehash: // stack: address, retdest - %mpt_read_state_trie - // stack: account_ptr, retdest - DUP1 ISZERO %jumpi(retzero) - %add_const(3) - // stack: codehash_ptr, retdest - %mload_trie_data + %read_code %mload_trie_data // stack: codehash, retdest SWAP1 JUMP -retzero: - %stack (account_ptr, retdest) -> (retdest, 0) - JUMP +} %macro extcodehash %stack (address) -> (address, %%after) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index 5f469b7e0..c1c2e0d5b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -19,7 +19,7 @@ global sys_create: -> (sys_create_got_address, value, code_offset, code_len, kexit_info) %address // stack: sender, sys_create_got_address, value, code_offset, code_len, kexit_info - DUP1 %nonce_from_addr + DUP1 %nonce // stack: nonce, sender, sys_create_got_address, value, code_offset, code_len, kexit_info SWAP1 // stack: sender, nonce, sys_create_got_address, value, code_offset, code_len, kexit_info @@ -80,7 +80,7 @@ global create_common: DUP2 %selfbalance LT %jumpi(create_insufficient_balance) // Increment the sender's nonce. %address - DUP1 %nonce_from_addr %eq_const(@MAX_NONCE) %jumpi(nonce_overflow) // EIP-2681 + DUP1 %nonce %eq_const(@MAX_NONCE) %jumpi(nonce_overflow) // EIP-2681 %increment_nonce // stack: address, value, code_offset, code_len, kexit_info @@ -271,7 +271,7 @@ global set_codehash: DUP1 %insert_touched_addresses DUP1 %read_code %mload_trie_data // stack: prev_codehash, addr, codehash, retdest - DUP2 %read_code_lenght %mload_trie_data + DUP2 %read_code_length %mload_trie_data %stack (prev_code_length, prev_codehash, addr) -> (addr, prev_codehash, prev_code_length, addr) %journal_add_code_change // Add the code change to the journal. // stack: addr, codehash, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm index 180839448..f974952b5 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm @@ -5,111 +5,59 @@ // stack: address DUP1 %insert_touched_addresses DUP1 %append_created_contracts - #[cfg(feature = eth_mainnet)] - { - %mpt_read_state_trie + %mpt_read_state_trie - // If the account doesn't exist, there's no need to check its balance or nonce, - // so we can skip ahead, setting existing_balance = existing_account_ptr = 0. - DUP1 ISZERO %jumpi(%%add_account) - - DUP1 %mload_trie_data// nonce = account[0] - // stack: nonce, existing_account_ptr, address - %jumpi(%%error_collision) - // stack: existing_account_ptr, address - // Check that the code is empty. - %add_const(3) - // stack: existing_codehash_ptr, address - DUP1 %mload_trie_data // codehash = account[3] - %eq_const(@EMPTY_STRING_HASH) ISZERO %jumpi(%%error_collision) - // stack: existing_codehash_ptr, address - %sub_const(2) %mload_trie_data // balance = account[1] - %jump(%%do_insert) + // If the account doesn't exist, there's no need to check its balance or nonce, + // so we can skip ahead, setting existing_balance = existing_account_ptr = 0. + DUP1 ISZERO %jumpi(%%add_account) + + DUP1 %mload_trie_data// nonce = account[0] + // stack: nonce, existing_account_ptr, address + %jumpi(%%error_collision) + // stack: existing_account_ptr, address + // Check that the code is empty. + %add_const(3) + // stack: existing_codehash_ptr, address + DUP1 %mload_trie_data // codehash = account[3] + %eq_const(@EMPTY_STRING_HASH) ISZERO %jumpi(%%error_collision) + // stack: existing_codehash_ptr, address + %sub_const(2) %mload_trie_data // balance = account[1] + %jump(%%do_insert) - %%add_account: - // stack: existing_balance, address - DUP2 PUSH 1 - // stack: is_contract, address, existing_balance, address - %journal_add_account_created - %%do_insert: - // stack: new_acct_value=existing_balance, address - // Write the new account's data to MPT data, and get a pointer to it. - %get_trie_data_size - // stack: account_ptr, new_acct_value, address - PUSH 0 DUP4 %journal_add_nonce_change - PUSH 1 %append_to_trie_data // nonce = 1 - // stack: account_ptr, new_acct_value, address - SWAP1 %append_to_trie_data // balance = new_acct_value - // stack: account_ptr, address - PUSH 0 %append_to_trie_data // storage_root = nil - // stack: account_ptr, address - PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') - // stack: account_ptr, address - SWAP1 - // stack: address, account_ptr - %addr_to_state_key - // stack: state_key, account_ptr - %mpt_insert_state_trie - // stack: (empty) - PUSH 0 // success - %jump(%%end) - - // If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. - // (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) - // So we return 1 to indicate an error. - %%error_collision: - %stack (existing_account_ptr, address) -> (1) - - %%end: - // stack: status - } - #[cfg(feature = cdk_erigon)] - { - POP - %read_code ISZERO %jumpi(%%add_account) - // Check that the nonce is 0. - // stack: address - DUP1 %nonce - // stack: nonce, address - %jumpi(%%error_collision) - // stack: address - // Check that the code is empty. - DUP1 %extcodehash - %eq_const(@EMPTY_STRING_POSEIDON_HASH) ISZERO %jumpi(%%error_collision) - DUP1 %balance - %jump(%%do_insert) - - %%add_account: - // stack: address - DUP1 PUSH 1 - // stack: is_contract, address, address - %journal_add_account_created - // stack: address - PUSH 0 - %%do_insert: - // stack: new_acct_value, address - // Write the new account's data to MPT data, and get a pointer to it. - // stack: new_acct_value, address - PUSH 0 DUP3 %journal_add_nonce_change - %stack (new_acct_value, address) -> (address, 1, new_acct_value, address) - %set_nonce // nonce = 1 - // stack: new_acct_value, address - DUP2 %set_balance // balance = new_acct_value - %stack (address) -> (address, @EMPTY_STRING_POSEIDON_HASH) - %set_code - // stack: empty - PUSH 0 // success - %jump(%%end) - - // If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. - // (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) - // So we return 1 to indicate an error. - %%error_collision: + %%add_account: + // stack: existing_balance, address + DUP2 PUSH 1 + // stack: is_contract, address, existing_balance, address + %journal_add_account_created + %%do_insert: + // stack: new_acct_value=existing_balance, address + // Write the new account's data to MPT data, and get a pointer to it. + %get_trie_data_size + // stack: account_ptr, new_acct_value, address + PUSH 0 DUP4 %journal_add_nonce_change + PUSH 1 %append_to_trie_data // nonce = 1 + // stack: account_ptr, new_acct_value, address + SWAP1 %append_to_trie_data // balance = new_acct_value + // stack: account_ptr, address + PUSH 0 %append_to_trie_data // storage_root = nil + // stack: account_ptr, address + PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') + // stack: account_ptr, address + SWAP1 + // stack: address, account_ptr + %addr_to_state_key + // stack: state_key, account_ptr + %mpt_insert_state_trie + // stack: (empty) + PUSH 0 // success + %jump(%%end) +// If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. +// (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) +// So we return 1 to indicate an error. +%%error_collision: %stack (address) -> (1) - - %%end: +%%end: // stack: status - } %endmacro %macro append_created_contracts diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 0b9c9b19f..6a006ef71 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -27,7 +27,7 @@ global process_normalized_txn: // stack: sender, retdest // Check that txn nonce matches account nonce. - DUP1 %nonce_from_addr + DUP1 %nonce DUP1 %eq_const(@MAX_NONCE) %assert_zero(invalid_txn_2) // EIP-2681 // stack: sender_nonce, sender, retdest %mload_txn_field(@TXN_FIELD_NONCE) @@ -117,7 +117,7 @@ global process_contract_creation_txn: %mload_txn_field(@TXN_FIELD_ORIGIN) // stack: origin, retdest - DUP1 %nonce_from_addr + DUP1 %nonce // stack: origin_nonce, origin, retdest %decrement // Need the non-incremented nonce SWAP1 diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm b/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm index be7b26add..d1ee78c01 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm @@ -53,7 +53,7 @@ deduct_eth_insufficient_balance: JUMP deduct_eth_delete_balance: %stack (balance, balance_ptr, addr, amount, retdest) -> (addr, retdest, 0) - %remove_balanace + %remove_balance // stack: retdest, 0 JUMP deduct_eth_noop: @@ -78,7 +78,7 @@ global add_eth: // stack: codehash, addr, amount, retdest ISZERO %jumpi(add_eth_new_account) // If the account is empty, we need to create the account. // stack: addr, amount, retdest - %key_balance DUP1 %read_key // TODO: replace with read_balance? + %key_balance DUP1 %search_key // TODO: replace with read_balance? DUP1 ISZERO %jumpi(add_eth_zero_balance) %stack (balance_ptr, key_balance, amount) -> (balance_ptr, amount, balance_ptr) // stack: balance_ptr, amount, balance_ptr, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index 174d9bf0e..d04b151dc 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -75,36 +75,61 @@ // stack: addr %mpt_read_state_trie // stack: account_ptr - DUP1 ISZERO %jumpi(%%false) + DUP1 ISZERO + } + #[cfg(feature = cdk_erigon)] + { + // stack: addr + DUP1 %read_nonce %mload_trie_data + // stack: nonce, addr + ISZERO %not_bit + } + %jumpi(%%false) + #[cfg(feature = eth_mainnet)] + { // stack: account_ptr DUP1 %mload_trie_data // stack: nonce, account_ptr - ISZERO %not_bit %jumpi(%%false) - %increment DUP1 %mload_trie_data - // stack: balance, balance_ptr - ISZERO %not_bit %jumpi(%%false) - %add_const(2) %mload_trie_data - // stack: code_hash - PUSH @EMPTY_STRING_HASH - EQ - %jump(%%after) + ISZERO %not_bit } - #[cfg(feature = cdk_erigon)] + #[cfg(feature = cdk_erigon)] { // stack: addr DUP1 %read_nonce %mload_trie_data // stack: nonce, addr - ISZERO %not_bit %jumpi(%%false) + ISZERO %not_bit + } + %jumpi(%%false) + #[cfg(feature = eth_mainnet)] + { + %increment DUP1 %mload_trie_data + // stack: balance, balance_ptr + ISZERO %not_bit + } + #[cfg(feature = cdk_erigon)] + { // stack: addr DUP1 %read_balance %mload_trie_data // stack: balance, addr - ISZERO %not_bit %jumpi(%%false) + ISZERO %not_bit + } + %jumpi(%%false) + #[cfg(feature = eth_mainnet)] + { + %add_const(2) %mload_trie_data + // stack: code_hash + PUSH @EMPTY_STRING_HASH + EQ + } + #[cfg(feature = cdk_erigon)] + { // stack: addr %read_code %mload_trie_data // stack: codehash %eq_const(@EMPTY_STRING_POSEIDON_HASH) %jump(%%after) - } + } + %jump(%%after) %%false: // stack: account_ptr POP 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 59676b4ad..2f6b1febc 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm @@ -45,7 +45,7 @@ revert_account_destroyed_contd: SWAP1 // Remove `prev_balance` from `target`'s balance. // stack: target, address, prev_balance, retdest - %key_balance DUP1 %read_key %mload_trie_data + %key_balance DUP1 %search_key %mload_trie_data // stack: target_balance, target_balance_key, address, prev_balance, retdest %stack (target_balance, target_balance_key, address, prev_balance) -> (target_balance, prev_balance, target_balance_key, address, prev_balance) // stack: target_balance, prev_balance, target_balance_key, address, prev_balance, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm deleted file mode 100644 index 385c9c0c1..000000000 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/state_linked_list.asm +++ /dev/null @@ -1,462 +0,0 @@ -/// The state linked list is stored in SEGMENT_ACCOUNTS_LINKED_LIST in the kernel memory (context=0). -/// The length of the segment is stored in @GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE. -/// Searching and inserting is done by guessing the predecessor in the list. -/// If the key isn't found in the array, it is inserted -/// at the correct location. The linked list is used to keep track of -/// inserted, modified and deleted accounts balances, nonces, storage, etc, during the execution, so that the -/// initial and final MPT state tries can be reconstructed at the end of the execution. -/// An empty astate linked list is written as -/// [@U256_MAX, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. -/// Each node is encoded using 4 values: -/// - 0: The key -/// - 1: The value -/// - 2: The initial value. -/// - 3: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. - -%macro store_initial_state - PUSH %%after - %jump(store_initial_state) -%%after: -%endmacro - - -/// Iterates over the initial state linked list and copies the values in the inital values slot. -/// Computes the length of `SEGMENT_STORAGE_LINKED_LIST` and -/// checks against `GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE`. -/// It also checks that the next node address is current address + 5 -/// and that all keys are strictly increasing. -/// NOTE: It may be more efficient to check that the next node addres != U256_MAX -/// (i.e. node was not deleted) and ensure that no node with repeated key -/// is ever read. -global store_initial_state: - // stack: retdest - PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE - PUSH @ACCOUNTS_STORAGE_LINKED_LIST - ADD - // stack: cur_len, retdest - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - DUP1 - MLOAD_GENERAL - // stack: current_key, current_node_ptr, cur_len, retdest - %assert_eq_const(@U256_MAX) - - // stack: current_node_ptr, cur_len', retdest - DUP1 - %next_node - // stack: next_node_ptr, current_node_ptr, cur_len, retdest - DUP1 - SWAP2 - %next_initial_node - %assert_eq(store_initial_state_end) // next_node_ptr == current_node_ptr + node_size - // stack: next_node_ptr, cur_len', retdest - -loop_store_initial_state: - // stack: current_node_ptr, cur_len, retdest - DUP1 - %increment - MLOAD_GENERAL - // stack: value, current_node_ptr, cur_len, retdest - DUP2 - %add_const(@STATE_COPY_PAYLOAD_PTR) - // stack: cpy_value_ptr, value, current_node_ptr, cur_len, retdest - SWAP1 - MSTORE_GENERAL // Store cpy_value - // stack: current_node_ptr, cur_len, retdest - SWAP1 PUSH @STATE_LINKED_LISTS_NODE_SIZE - ADD - SWAP1 - // Check correctness of next node ptr and strict key monotonicity. - DUP1 - MLOAD_GENERAL - // stack: current_key, current_node_ptr, cur_len', retdest - SWAP1 - DUP1 - %next_node - // stack: next_node_ptr, current_node_ptr, current_key, cur_len', retdest - DUP1 - SWAP2 - %next_initial_node - %assert_eq(store_initial_state_end_pop_key) // next_node_ptr == current_node_ptr + node_size - // stack: next_node_ptr, current_key, cur_len', retdest - SWAP1 - DUP2 - MLOAD_GENERAL - %assert_gt // next_key > current_key - // stack: next_node_ptr, cur_len', retdest - %jump(loop_store_initial_accounts) - -store_initial_state_end_pop_key: - // stack: next_node_ptr, current_key, cur_len', retdest - SWAP1 POP - -store_state_slots_end: - // stack: next_node_ptr, cur_len', retdest - %assert_eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) - - // stack: cur_len, retdest - DUP1 - %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) - %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) - JUMP - - -// 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_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. -%macro get_valid_state_ptr - // stack: ptr/4 - // Check that the pointer is greater than the segment. - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - DUP2 - %mul_const(4) - // stack: ptr, @SEGMENT_ACCOUNTS_LINKED_LIST, ptr/4 - %increment %assert_gt - // stack: ptr/4 - DUP1 - PUSH 4 - %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 - // stack: @SEGMENT_ACCOUNTS_LINKED_LIST/4 + accounts_linked_list_len/4, ptr/4, ptr/4 - %assert_gt - %mul_const(4) -%endmacro - -%macro set_nonce - // stack: address, nonce - %key_nonce - %insert_key - // stack: (empty) -%endmacro - -%macro set_balance - // stack: address, balance - %key_balance - %insert_key - // stack: (empty) -%endmacro - -%macro set_code - // stack: address, code - %key_code - %insert_key - // stack: (empty) -%endmacro - -%macro set_code_length - // stack: address, code_lenght - %key_code_lenght - %insert_key - // stack: (empty) -%endmacro - - -%macro insert_slot - // stack: addr, slot, value - %addr_to_state_key - %key_storage - %insert_key - // stack: (empty) -%endmacro - -%macro insert_slot_from_addr_key - // stack: addr_key, slot_key, value - %key_storage - %insert_key - // stack: (empty) -%endmacro - - -%macro insert_key - %stack (key, value) -> (key, value, %%after) - %jump(insert_key) - %%after: -%endmacro - -/// Inserts the pair `(key, value)` into the linked list if `key` was not already present, -/// or modifies the vealue if it was already present. -global insert_key: - // stack: key, value, retdest - PROVER_INPUT(linked_list::insert_state) - // stack: pred_ptr/4, key, value, retdest - %get_valid_state_ptr - - // stack: pred_ptr, key, value, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_key, pred_key, pred_ptr, key, value, retdest - DUP4 - GT - DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // we need to insert a new node. - %jumpi(insert_new_key) - // stack: pred_key, pred_ptr, key, value, retdest - // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - // stack: pred_ptr, key, value, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, key_found_with_overwrite) - // The key is not in the list. - PANIC - -key_found_with_overwrite: - // The key was already in the list - // stack: pred_ptr, key, value, retdest - // Load the payload pointer - %increment - // stack: payload_ptr_ptr, key, value, retdest - DUP3 MSTORE_GENERAL - %pop2 - JUMP - -insert_new_key: - // stack: pred_key, pred_ptr, key, value, retdest - POP - // get the value of the next address - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - // stack: next_ptr_ptr, key, value, retdest - %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) - DUP2 - MLOAD_GENERAL - // stack: next_ptr, new_ptr, next_ptr_ptr, key, value, retdest - // Check that this is not a deleted node - DUP1 - %eq_const(@U256_MAX) - %assert_zero - DUP1 - MLOAD_GENERAL - // stack: next_key, next_ptr, new_ptr, next_ptr_ptr, key, value, retdest - DUP5 - // Here, (key > pred_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). - // We should have (key < next_key), meaning the new value can be inserted between pred_ptr and next_ptr. - %assert_lt - // stack: next_ptr, new_ptr, next_ptr_ptr, key, value, retdest - SWAP2 - DUP2 - // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, key, value, retdest - MSTORE_GENERAL - // stack: new_ptr, next_ptr, key, value, retdest - DUP1 - DUP4 - MSTORE_GENERAL - // stack: new_ptr, next_ptr, key, value, retdest - %increment - DUP1 - DUP5 - MSTORE_GENERAL - // stack: new_ptr + 1, next_ptr, key, value, retdest - %add_const(2) // TODO: We're skiping the initial value. This shuould also done with the accounts bc this value should't be used. - DUP1 - // stack: new_next_ptr, new_next_ptr, next_ptr, key, value, retdest - SWAP2 - MSTORE_GENERAL - // stack: new_next_ptr, key, value, retdest - %increment - %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) - // stack: key, value, retdest - %pop2 - JUMP - - -/// Searches the key in the state the linked list. If the key is stored -/// returns the current value of the key, or 0 otherwise. -global search_key: - // stack: key, retdest - PROVER_INPUT(linked_list::search_state) - // stack: pred_ptr/4, key, retdest - %get_valid_state_ptr - - // stack: pred_ptr, key, retdest - DUP1 - MLOAD_GENERAL - DUP1 - // stack: pred_key, pred_key, pred_ptr, key, retdest - DUP4 - GT - DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) - ADD // OR - // If the predesessor is strictly smaller or the predecessor is the special - // node with key @U256_MAX (and hence we're inserting a new minimum), then - // the key was not found. - %jumpi(key_not_found) - // stack: pred_addr_key, pred_ptr, addr_key, key, retdest - // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. - DUP3 - %assert_eq - // stack: pred_ptr, key, retdest - // Check that this is not a deleted node - DUP1 - %add_const(@STATE_NEXT_NODE_PTR) - MLOAD_GENERAL - %jump_neq_const(@U256_MAX, key_found) - // The key is not in the list. - PANIC - -key_found: - // The key was already in the list. - // stack: pred_ptr, key, retdest - %increment - MLOAD_GENERAL - // stack: value, key, retdest - %stack (value, key, retdest) -> (retdest, value) - JUMP - -key_not_found: - // stack: pred_key, pred_ptr, key, retdest - %stack (pred_key, pred_ptr, key, retdest) -> (retdest, 0) - JUMP - -%macro search_key - %stack (key) -> (key, %%after) - %jump(search_key) -%%after: - // stack: value -%endmacro -%macro search_slot_from_addr_key - // stack: addr_key, slot - %key_storage - %search_key -%endmacro - -%macro read_balance - // stack: addr_key - %key_balance - %search_key -%endmacro - -%macro read_code - // stack: addr_key - %key_code - %search_key - // stack: code_hash -%endmacro - -%macro read_code_lenght - // stack: addr_key - %key_code_length - %search_key - // stack: code_length -%endmacro - -%macro read_nonce - // stack: addr_key - %key_nonce - %search_key - // stack: nonce -%endmacro - -%macro remove_key - PUSH %%after - SWAP1 - %jump(remove_key) -%%after: -%endmacro - -%macro remove_balance - %key_balance - %remove_key -%endmacro - -%macro remove_slot_from_addr_key - %key_storage - %remove_key -%endmacro - -/// Removes the key and its value from the state linked list. -/// Panics if the key is not in the list. -global remove_key: - // stack: key, retdest - PROVER_INPUT(linked_list::remove_slot) - // stack: pred_ptr/4, key, retdest - %get_valid_state_ptr - // stack: pred_ptr, key, retdest - %add_const(@STATE_NEXT_NODE_PTR) - // stack: next_ptr_ptr, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_ptr, next_ptr_ptr, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_key, next_ptr, next_ptr_ptr, key, retdest - DUP4 - %assert_eq - // stack: next_ptr, next_ptr_ptr, key, retdest - %add_const(@STATE_NEXT_NODE_PTR) - // stack: next_next_ptr_ptr, next_ptr_ptr, key, retdest - DUP1 - MLOAD_GENERAL - // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, key, retdest - SWAP1 - %mstore_u256_max - // stack: next_next_ptr, next_ptr_ptr, key, retdest - MSTORE_GENERAL - POP - JUMP - -%macro read_slot_from_current_addr - // stack: slot - %address - %addr_to_state_key - %key_storage - %stack (storage_key) -> (storage_key, %%after) - // stack: storage_key, %%after - %jump(search_key) -%%after: - // stack: slot_value -%endmacro - -%macro read_slot_from_addr_key - // stack: state_key, slot - %slot_to_storage_key - %stack (storage_key) -> (storage_key, %%after) - %jump(search_key) -%%after: - // stack: slot_value -%endmacro - -%macro read_slot_from_addr - // stack: address, slot - %addr_to_state_key - %key_storage - %stack (storage_key_found) -> (storage_key, %%after) - // stack: storage_key, %%after - %jump(search_key) -%%after: - // stack: slot_value -%endmacro - -%macro first_node - // stack: empty - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - %next_slot -%endmacro - -%macro first_initial_node - // stack: empty - PUSH @SEGMENT_ACCONTS_LINKED_LIST - %next_initial_node -%endmacro - -%macro next_node - // stack: node_ptr - %add_const(@ACCOUNTS_NEXT_NODE_PTR) - MLOAD_GENERAL - // stack: next_node_ptr -%endmacro - -%macro next_initial_node - // stack: node_ptr - %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) - // stack: next_node_ptr -%endmacro \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index e72c20ee6..89748d5bc 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -76,8 +76,15 @@ global main: global store_initial: // Store the initial accounts and slots for hashing later - %store_initial_accounts - %store_initial_slots + #[cfg(feature = eth_mainnet)] + { + %store_initial_accounts + %store_initial_slots + } + #[cfg(feature = cdk_erigon)] + { + %store_initial_state + } global after_store_initial: // Initialize the transaction and receipt trie root pointers. 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 c878ae812..167f56523 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm @@ -23,19 +23,22 @@ mpt_delete_leaf: PUSH 0 // empty node ptr SWAP1 JUMP -global delete_account: - %addr_to_state_key - DUP1 - %remove_account_from_linked_list - // stack: addr_to_state_key, retdest +#[cfg(feature = eth_mainnet)] +{ + global delete_account: + %addr_to_state_key + DUP1 + %remove_account_from_linked_list + // stack: addr_to_state_key, retdest - // Now we also need to remove all the storage nodes associated with the deleted account. - %remove_all_account_slots - JUMP + // Now we also need to remove all the storage nodes associated with the deleted account. + %remove_all_account_slots + JUMP -%macro delete_account - %stack (address) -> (address, %%after) - %jump(delete_account) -%%after: - // stack: (empty) -%endmacro + %macro delete_account + %stack (address) -> (address, %%after) + %jump(delete_account) + %%after: + // stack: (empty) + %endmacro +} diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm index e4e6061e4..504e1458d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm @@ -4,16 +4,21 @@ // Pre stack: key, value_ptr, retdest // Post stack: (empty) // TODO: Have this take an address and do %mpt_insert_state_trie? To match mpt_read_state_trie. -global mpt_insert_state_trie: - // stack: key, value_ptr, retdest - %insert_account_with_overwrite - JUMP +#[cfg(feature = eth_mainnet)] +{ + global mpt_insert_state_trie: + // stack: key, value_ptr, retdest + %insert_account_with_overwrite + JUMP -%macro mpt_insert_state_trie - %stack (key, value_ptr) -> (key, value_ptr, %%after) - %jump(mpt_insert_state_trie) -%%after: -%endmacro + + %macro mpt_insert_state_trie + %stack (key, value_ptr) -> (key, value_ptr, %%after) + %jump(mpt_insert_state_trie) + %%after: + %endmacro + +} // Insert a node in the transaction trie. The payload // must be pointing to the rlp encoded txn diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm index 0c683c7d9..12a5fce4c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm @@ -1,20 +1,23 @@ // Given an address, return a pointer to the associated account data, which // consists of four words (nonce, balance, storage_root, code_hash), in the // trie_data segment. Return null if the address is not found. -global mpt_read_state_trie: - // stack: addr, retdest - %read_account_from_addr - // stack: account_ptr, retdest - SWAP1 - // stack: retdest, account_ptr - JUMP +#[cfg(feature = eth_mainnet)] +{ + global mpt_read_state_trie: + // stack: addr, retdest + %read_account_from_addr + // stack: account_ptr, retdest + SWAP1 + // stack: retdest, account_ptr + JUMP -// Convenience macro to call mpt_read_state_trie and return where we left off. -%macro mpt_read_state_trie - %stack (addr) -> (addr, %%after) - %jump(mpt_read_state_trie) -%%after: -%endmacro + // Convenience macro to call mpt_read_state_trie and return where we left off. + %macro mpt_read_state_trie + %stack (addr) -> (addr, %%after) + %jump(mpt_read_state_trie) + %%after: + %endmacro +} // Read a value from a MPT. // diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm index d7b81d0f7..17513c7cd 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -103,6 +103,14 @@ sstore_after_refund: %stack (kexit_info, current_value, slot, value) -> (value, current_value, current_value, slot, value, kexit_info) EQ %jumpi(sstore_noop) + // stack: current_value, slot, value, kexit_info + DUP1 ISZERO + // stack: current_value==0, current_value, slot, value, kexit_info + DUP4 MUL + // stack: value & current_value==0, current_value, slot, value, kexit_info + %jumpi(new_storage_slot) +global not_new_storage_slot: + // stack: current_value, slot, value, kexit_info DUP2 %address %journal_add_storage_change // stack: slot, value, kexit_info @@ -133,3 +141,34 @@ sstore_delete: // stack: value, kexit_info POP EXIT_KERNEL + +%macro insert_new_storage_slot + // stack: address, slot + %mload_global_metadata(@GLOBAL_METADATA_NEW_STORAGE_SLOTS_LEN) + // stack: list_len, address, slot + DUP1 %add_const(@SEGMENT_NEW_STORAGE_SLOTS) + // stack: index, list_len, address, slot + DUP1 %add_const(1) + %stack (index_plus_1, index, list_len, address, slot) -> (address, index, slot, index_plus_1, list_len) + MSTORE_GENERAL MSTORE_GENERAL + // stack: list_len + %add_const(2) + // stack: list_len+2 + %mstore_global_metadata(@GLOBAL_METADATA_NEW_STORAGE_SLOTS_LEN) + // stack: (empty) +%endmacro + +new_storage_slot: + // stack: current_value, slot, value, kexit_info + %address DUP1 %contract_just_created + // stack: contract_just_created, address, current_value, slot, value, kexit_info + %jumpi(new_storage_slot_new_contract) + // stack: address, current_value, slot, value, kexit_info + POP %jump(not_new_storage_slot) +new_storage_slot_new_contract: + // stack: address, current_value, slot, value, kexit_info + DUP3 SWAP1 + // stack: address, slot, current_value, slot, value, kexit_info + %insert_new_storage_slot + // stack: current_value, slot, value, kexit_info + %jump(not_new_storage_slot) diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm index 701bd4193..f0fba3897 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/delete.asm @@ -209,9 +209,9 @@ global delete_account: %stack (address, retdest) -> (address, retdest) DUP1 %key_nonce // stack: key_nonce, address, retdest - DUP1 %smt_read_state ISZERO %jumpi(zero_nonce) + DUP1 %search_key ISZERO %jumpi(zero_nonce) // stack: key_nonce, address, retdest - DUP1 %smt_delete_state + DUP1 %remove_key // stack: key_nonce, address, retdest zero_nonce: // stack: key_nonce, address, retdest @@ -219,9 +219,9 @@ zero_nonce: // stack: address, retdest DUP1 %key_balance // stack: key_balance, address, retdest - DUP1 %smt_read_state ISZERO %jumpi(zero_balance) + DUP1 %search_key ISZERO %jumpi(zero_balance) // stack: key_balance, address, retdest - DUP1 %smt_delete_state + DUP1 %remove_key // stack: key_balance, address, retdest zero_balance: // stack: key_balance, address, retdest @@ -229,9 +229,9 @@ zero_balance: // stack: address, retdest DUP1 %key_code // stack: key_code, address, retdest - DUP1 %smt_read_state ISZERO %jumpi(zero_code) + DUP1 %search_key ISZERO %jumpi(zero_code) // stack: key_code, address, retdest - DUP1 %smt_delete_state + DUP1 %remove_key // stack: key_code, address, retdest zero_code: // stack: key_code, address, retdest @@ -239,9 +239,9 @@ zero_code: // stack: address, retdest DUP1 %key_code_length // stack: key_code_length, address, retdest - DUP1 %smt_read_state ISZERO %jumpi(zero_code_length) + DUP1 %search_key ISZERO %jumpi(zero_code_length) // stack: key_code_length, address, retdest - DUP1 %smt_delete_state + DUP1 %remove_key zero_code_length: // N.B.: We don't delete the storage, since there's no way of knowing keys used. // stack: key_code_length, address, retdest @@ -272,9 +272,9 @@ delete_storage_slot: // stack: slot, i, slots_len, address, retdest DUP4 %key_storage // stack: key_storage, i, slots_len, address, retdest - DUP1 %smt_read_state ISZERO %jumpi(zero_slot) + DUP1 %search_key ISZERO %jumpi(zero_slot) // stack: key_storage, i, slots_len, address, retdest - DUP1 %smt_delete_state + DUP1 %remove_key zero_slot: // stack: key_storage, i, slots_len, address, retdest POP diff --git a/evm_arithmetization/src/cpu/kernel/assembler.rs b/evm_arithmetization/src/cpu/kernel/assembler.rs index 8c4fb2fb0..bd5bab3ee 100644 --- a/evm_arithmetization/src/cpu/kernel/assembler.rs +++ b/evm_arithmetization/src/cpu/kernel/assembler.rs @@ -457,7 +457,7 @@ fn push_target_size(target: &PushTarget) -> u8 { match target { PushTarget::Literal(n) => u256_to_trimmed_be_bytes(n).len() as u8, PushTarget::Label(_) => BYTES_PER_OFFSET, - PushTarget::MacroLabel(v) => panic!("Macro label not in a macro: {v}"), + PushTarget::MacroLabel(v) => BYTES_PER_OFFSET, PushTarget::MacroVar(v) => panic!("Variable not in a macro: {v}"), PushTarget::Constant(c) => panic!("Constant wasn't inlined: {c}"), } diff --git a/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs b/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs index 49fa18d78..37c4d8dca 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs @@ -115,10 +115,13 @@ pub(crate) enum GlobalMetadata { /// Address where the base fee to be burnt is sent. BurnAddr, + + /// Number of used storage slots in newly created contracts. + NewStorageSlotsLen, } impl GlobalMetadata { - pub(crate) const COUNT: usize = 55; + pub(crate) const COUNT: usize = 56; /// Unscales this virtual offset by their respective `Segment` value. pub(crate) const fn unscale(&self) -> usize { @@ -182,6 +185,7 @@ impl GlobalMetadata { Self::TransientStorageLen, Self::BlobVersionedHashesLen, Self::BurnAddr, + Self::NewStorageSlotsLen, ] } @@ -249,6 +253,7 @@ impl GlobalMetadata { Self::TransientStorageLen => "GLOBAL_METADATA_TRANSIENT_STORAGE_LEN", Self::BlobVersionedHashesLen => "GLOBAL_METADATA_BLOB_VERSIONED_HASHES_LEN", Self::BurnAddr => "GLOBAL_METADATA_BURN_ADDR", + Self::NewStorageSlotsLen => "GLOBAL_METADATA_NEW_STORAGE_SLOTS_LEN", } } } diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 27322bec5..39b51debb 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use ethereum_types::{Address, H160, H256, U256}; use hex_literal::hex; +use smt_type::PartialSmtType; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; @@ -15,6 +16,7 @@ pub(crate) mod context_metadata; mod exc_bitfields; pub(crate) mod global_metadata; pub(crate) mod journal_entry; +pub(crate) mod smt_type; pub(crate) mod trie_type; pub(crate) mod txn_fields; @@ -68,6 +70,7 @@ pub(crate) fn evm_constants() -> HashMap { c.insert(MAX_NONCE.0.into(), U256::from(MAX_NONCE.1)); c.insert(CALL_STACK_LIMIT.0.into(), U256::from(CALL_STACK_LIMIT.1)); + c.insert(POSEIDON_HASH_ZEROS.0.into(), POSEIDON_HASH_ZEROS.1); c.insert( MAX_RLP_PREFIX_SIZE.0.into(), U256::from(MAX_RLP_PREFIX_SIZE.1), @@ -135,6 +138,9 @@ pub(crate) fn evm_constants() -> HashMap { for trie_type in PartialTrieType::all() { c.insert(trie_type.var_name().into(), (trie_type as u32).into()); } + for trie_type in PartialSmtType::all() { + c.insert(trie_type.var_name().into(), (trie_type as u32).into()); + } for entry in JournalEntry::all() { c.insert(entry.var_name().into(), (entry as u32).into()); } @@ -177,7 +183,7 @@ const MISC_CONSTANTS: [(&str, [u8; 32]); 4] = [ ), ]; -const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [ +const HASH_CONSTANTS: [(&str, [u8; 32]); 3] = [ // Hash of an empty string: keccak(b'').hex() ( "EMPTY_STRING_HASH", @@ -188,6 +194,10 @@ const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [ "EMPTY_NODE_HASH", hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), ), + ( + "EMPTY_STRING_POSEIDON_HASH", + hex!("3baed9289a384f6c1c05d92b56c801c2d2e2a7050d6c16538b814fa186835c79"), + ), ]; const EC_CONSTANTS: [(&str, [u8; 32]); 25] = [ @@ -383,6 +393,16 @@ const CODE_SIZE_LIMIT: [(&str, u64); 3] = [ const MAX_NONCE: (&str, u64) = ("MAX_NONCE", 0xffffffffffffffff); const CALL_STACK_LIMIT: (&str, u64) = ("CALL_STACK_LIMIT", 1024); +const POSEIDON_HASH_ZEROS: (&str, U256) = ( + "POSEIDON_HASH_ZEROS", + U256([ + 4330397376401421145, + 14124799381142128323, + 8742572140681234676, + 14345658006221440202, + ]), +); + // 9 bytes, largest possible RLP prefix in our MPTs. const MAX_RLP_PREFIX_SIZE: (&str, u8) = ("MAX_RLP_PREFIX_SIZE", 9); // Address where RLP encoding generally starts. @@ -391,12 +411,13 @@ const MAX_RLP_PREFIX_SIZE: (&str, u8) = ("MAX_RLP_PREFIX_SIZE", 9); pub(crate) const INITIAL_RLP_ADDR: (&str, usize) = ("INITIAL_RLP_ADDR", Segment::RlpRaw as usize + 1); -const LINKED_LISTS_CONSTANTS: [(&str, u16); 7] = [ +const LINKED_LISTS_CONSTANTS: [(&str, u16); 8] = [ ("ACCOUNTS_LINKED_LISTS_NODE_SIZE", 4), ("STORAGE_LINKED_LISTS_NODE_SIZE", 5), ("STATE_LINKED_LISTS_NODE_SIZE", 4), ("ACCOUNTS_NEXT_NODE_PTR", 3), ("STORAGE_NEXT_NODE_PTR", 4), + ("STATE_NEXT_NODE_PTR", 3), ("STORAGE_COPY_PAYLOAD_PTR", 3), ("STATE_COPY_PAYLOAD_PTR", 4), ]; diff --git a/evm_arithmetization/src/cpu/kernel/opcodes.rs b/evm_arithmetization/src/cpu/kernel/opcodes.rs index 6491003f1..fde72e247 100644 --- a/evm_arithmetization/src/cpu/kernel/opcodes.rs +++ b/evm_arithmetization/src/cpu/kernel/opcodes.rs @@ -39,6 +39,8 @@ pub fn get_opcode(mnemonic: &str) -> u8 { "SAR" => 0x1d, "KECCAK256" => 0x20, "KECCAK_GENERAL" => 0x21, + "POSEIDON" => 0x22, + "POSEIDON_GENERAL" => 0x23, "ADDRESS" => 0x30, "BALANCE" => 0x31, "ORIGIN" => 0x32, diff --git a/evm_arithmetization/src/memory/segments.rs b/evm_arithmetization/src/memory/segments.rs index e1b6678f6..2796a95ee 100644 --- a/evm_arithmetization/src/memory/segments.rs +++ b/evm_arithmetization/src/memory/segments.rs @@ -86,6 +86,8 @@ pub(crate) enum Segment { CreatedContracts = 37 << SEGMENT_SCALING_FACTOR, /// Blob versioned hashes specified in a type-3 transaction. TxnBlobVersionedHashes = 38 << SEGMENT_SCALING_FACTOR, + /// List of used storage slots in newly created contracts. + NewStorageSlots = 39 << SEGMENT_SCALING_FACTOR, } // These segments are not zero-initialized. @@ -97,7 +99,7 @@ pub(crate) const PREINITIALIZED_SEGMENTS_INDICES: [usize; 4] = [ ]; impl Segment { - pub(crate) const COUNT: usize = 39; + pub(crate) const COUNT: usize = 40; /// Unscales this segment by `SEGMENT_SCALING_FACTOR`. pub(crate) const fn unscale(&self) -> usize { @@ -145,6 +147,7 @@ impl Segment { Self::TransientStorage, Self::CreatedContracts, Self::TxnBlobVersionedHashes, + Self::NewStorageSlots, ] } @@ -190,6 +193,7 @@ impl Segment { Segment::TransientStorage => "SEGMENT_TRANSIENT_STORAGE", Segment::CreatedContracts => "SEGMENT_CREATED_CONTRACTS", Segment::TxnBlobVersionedHashes => "SEGMENT_TXN_BLOB_VERSIONED_HASHES", + Segment::NewStorageSlots => "SEGMENT_NEW_STORAGE_SLOTS", } } @@ -234,6 +238,7 @@ impl Segment { Segment::TransientStorage => 256, Segment::CreatedContracts => 256, Segment::TxnBlobVersionedHashes => 256, + Segment::NewStorageSlots => 256, } } } From 05935e58332aab0e1f10868f52f031cad54b7076 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Fri, 4 Oct 2024 17:47:41 +0200 Subject: [PATCH 11/60] Debugging erc20 --- Cargo.lock | 1 + .../src/cpu/kernel/aggregator.rs | 4 +- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 22 ++++-- .../src/cpu/kernel/asm/core/util.asm | 1 - .../src/cpu/kernel/asm/main.asm | 15 +--- .../src/cpu/kernel/constants/mod.rs | 2 +- .../src/generation/prover_input.rs | 24 ++++-- evm_arithmetization/src/witness/transition.rs | 22 ++++++ smt_trie/Cargo.toml | 1 + smt_trie/src/smt.rs | 74 +++++++++++++++---- 10 files changed, 119 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 770f7253f..46fbc04f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4585,6 +4585,7 @@ version = "0.1.1" dependencies = [ "ethereum-types", "hex-literal", + "log", "plonky2", "rand", "serde", diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index ce1928cfd..b4ff8118f 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 157 + 158 } else { // unreachable 0 @@ -178,6 +178,8 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/smt/utils.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/delete.asm"), + #[cfg(feature = "cdk_erigon")] + include_str!("asm/smt/read.asm"), include_str!("asm/journal/journal.asm"), include_str!("asm/journal/account_loaded.asm"), include_str!("asm/journal/account_destroyed.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index 2aea67b22..e3d78206f 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -97,16 +97,22 @@ global create_scalable_l2_account: // stack: (empty) PUSH update_scalable_block_number // stack: retdest - %get_trie_data_size // pointer to new account we're about to create - // stack: new_account_ptr, retdest - PUSH 0 %append_to_trie_data // nonce - PUSH 0 %append_to_trie_data // balance - PUSH 0 %append_to_trie_data // storage root pointer - PUSH @EMPTY_STRING_HASH %append_to_trie_data // code hash // stack: new_account_ptr, retdest + PUSH 0 + PUSH @ADDRESS_SCALABLE_L2_STATE_KEY + %set_nonce + + PUSH 0 + PUSH @ADDRESS_SCALABLE_L2_STATE_KEY + %set_balance // balance + + PUSH @EMPTY_STRING_HASH + PUSH @ADDRESS_SCALABLE_L2_STATE_KEY + %set_codehash // code hash + + PUSH 0 PUSH @ADDRESS_SCALABLE_L2_STATE_KEY - // stack: key, new_account_ptr, retdest - %jump(mpt_insert_state_trie) + %set_code_length // code_length %macro write_scalable_storage // stack: slot, value diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index d04b151dc..8dcb730d8 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -127,7 +127,6 @@ %read_code %mload_trie_data // stack: codehash %eq_const(@EMPTY_STRING_POSEIDON_HASH) - %jump(%%after) } %jump(%%after) %%false: diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 89748d5bc..2d25a6612 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -96,20 +96,10 @@ global after_store_initial: global hash_initial_tries: // We compute the length of the trie data segment in `mpt_hash` so that we // can check the value provided by the prover. - // The trie data segment is already written by the linked lists + // The trie data segment contains only the empty node - // First, we compute the initial size of the trie data segment. - PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE - PUSH @SEGMENT_ACCOUNTS_LINKED_LIST - %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) - SUB - // stack: accounts_ll_full_len, accounts_ll_node_size - DIV - %decrement - // stack: actual_nb_accounts // The initial payloads are written twice, and each payload requires 4 elements. - PUSH 8 MUL - %increment + PUSH 2 // stack: init_trie_data_len PUSH @INITIAL_RLP_ADDR // stack: rlp_start, init_trie_data_len @@ -120,6 +110,7 @@ global hash_initial_tries: // stack: trie_data_full_len // Check that the trie data length is correct. %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) +global debug_el_size: %assert_eq global start_txns: diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 39b51debb..65eb4afba 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -419,7 +419,7 @@ const LINKED_LISTS_CONSTANTS: [(&str, u16); 8] = [ ("STORAGE_NEXT_NODE_PTR", 4), ("STATE_NEXT_NODE_PTR", 3), ("STORAGE_COPY_PAYLOAD_PTR", 3), - ("STATE_COPY_PAYLOAD_PTR", 4), + ("STATE_COPY_PAYLOAD_PTR", 2), ]; /// Cancun-related constants diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 592f84e13..f76bc3009 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -358,8 +358,7 @@ impl GenerationState { #[cfg(feature = "eth_mainnet")] fn run_linked_list(&mut self, input_fn: &ProverInputFn) -> Result { match input_fn.0[1].as_str() { - "insert_account" | "search_account" => - self.run_next_insert_account(input_fn), + "insert_account" | "search_account" => self.run_next_insert_account(input_fn), "remove_account" => self.run_next_remove_account(), "insert_slot" | "search_slot" => self.run_next_insert_slot(input_fn), @@ -373,10 +372,18 @@ impl GenerationState { /// jump address. #[cfg(feature = "cdk_erigon")] fn run_linked_list(&mut self, input_fn: &ProverInputFn) -> Result { + use crate::generation::linked_list::StateLinkedList; + let mem = self.memory.get_preinit_memory(Segment::AccountsLinkedList); + log::debug!( + "state ll = {:?}", + StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + ); + log::debug!("state btree = {:?}", self.state_pointers); + log::debug!("input state = {}", self.inputs.trimmed_tries.state_trie); + match input_fn.0[1].as_str() { - "insert_state" => - self.run_next_insert_state(input_fn), - "remove_statt" => self.run_next_remove_state(), + "insert_state" | "search_state" => self.run_next_insert_state(input_fn), + "remove_state" => self.run_next_remove_state(), _ => Err(ProgramError::ProverInputError(InvalidInput)), } } @@ -554,7 +561,7 @@ impl GenerationState { .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); - if pred_key != key && input_fn.0[1].as_str() == "insert_account" { + if pred_key != key && input_fn.0[1].as_str() == "insert_state" { self.state_pointers.insert( key, u256_to_usize( @@ -616,7 +623,7 @@ impl GenerationState { Ok(U256::from(ptr / ACCOUNTS_LINKED_LIST_NODE_SIZE)) } - /// Returns a pointer `ptr` to a node of the form [..] -> [next_key, ..] + /// Returns a pointer `ptr` to a node of the form [..] -> [next_key, ..] /// list such that `next_key = addr` and `key` is the top of the stack. /// If the element is not in the list, returns an error. #[cfg(feature = "cdk_erigon")] @@ -682,7 +689,8 @@ impl GenerationState { (pred_ptr - Segment::StorageLinkedList as usize) / STORAGE_LINKED_LIST_NODE_SIZE, )) } - // TODO: We're missing a cdk_erigon counterpart for `run_next_remove_address_slots` + // TODO: We're missing a cdk_erigon counterpart for + // `run_next_remove_address_slots` /// Returns the first part of the KZG precompile output. fn run_kzg_point_eval(&mut self) -> Result { diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index fa66bee5b..ee0d858ce 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -308,6 +308,28 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ), ); + // state.log( + // level, + // format!( + // "state memory = {:?}", + // state + // .get_generation_state() + // .memory + // .get_preinit_memory(Segment::AccountsLinkedList), + // ), + // ); + // state.log( + // level, + // format!( + // "smt = {}", + // state + // .get_generation_state() + // .inputs + // .trimmed_tries + // .state_trie + // ), + // ); + assert!(pc < KERNEL.code.len(), "Kernel PC is out of range: {}", pc); } diff --git a/smt_trie/Cargo.toml b/smt_trie/Cargo.toml index 08a05a0fb..2907c63e7 100644 --- a/smt_trie/Cargo.toml +++ b/smt_trie/Cargo.toml @@ -19,6 +19,7 @@ hex-literal = { workspace = true } plonky2 = { workspace = true } rand = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } +log = { workspace = true } [lints] workspace = true diff --git a/smt_trie/src/smt.rs b/smt_trie/src/smt.rs index 2f394f585..9240596c5 100644 --- a/smt_trie/src/smt.rs +++ b/smt_trie/src/smt.rs @@ -1,7 +1,9 @@ #![allow(clippy::needless_range_loop)] +use core::fmt::Debug; use std::borrow::Borrow; use std::collections::{BTreeMap, HashMap, HashSet}; +use std::fmt::{Display, Formatter}; use ethereum_types::U256; use plonky2::field::goldilocks_field::GoldilocksField; @@ -11,7 +13,7 @@ use plonky2::plonk::config::Hasher; use serde::{Deserialize, Serialize}; use crate::bits::Bits; -use crate::db::Db; +use crate::db::{Db, MemoryDb}; use crate::utils::{ f2limbs, get_unique_sibling, hash0, hash_key_hash, hashout2u, key2u, limbs2f, u2h, u2k, }; @@ -440,27 +442,56 @@ impl Smt { v } - pub fn load_linked_list_data( + pub fn load_linked_list_data( &self, linked_list_mem: &mut Vec>, state_ptrs: &mut BTreeMap, ) { - let key = Key(self.root.elements); + let mut kv_sorted_by_k: Vec<(U256, U256)> = self + .kv_store + .iter() + .map(|(&key, &val)| (key2u(key), val)) + .collect(); + kv_sorted_by_k.sort_by(|(k1, _), (k2, _)| k1.cmp(k2)); + // The next node of the dummy node must be the first node. If the + // list is empty, this value is set to its original value after + // the loop + linked_list_mem[3] = Some(U256::from(OFFSET + 4)); + for (i, &(key, value)) in kv_sorted_by_k.iter().enumerate() { + // The nibbles are the address. + linked_list_mem.push(Some(key)); + log::debug!("setting linked_list_mem[i + 0] to {:?}", key); + // Set the value. + linked_list_mem.push(Some(value)); + log::debug!("setting linked_list_mem[i + 1] to {:?}", value); + // Set the original value. + linked_list_mem.push(Some(value)); + log::debug!("setting linked_list_mem[i + 2] to {:?}", value); + // Set the next node as the initial node. + linked_list_mem.push(Some(U256::from(OFFSET + 4 * (i + 2)))); + log::debug!("setting linked_list_mem[i + 3] to {:?}", U256::from(OFFSET)); - load_linked_list_data_with_key_and_bits::<_, O>( - self, - key, - Bits::empty(), - linked_list_mem, - state_ptrs, - ); + // Put the pointer in state_ptrs + state_ptrs.insert(key, OFFSET + 4 * (i + 1)); + } + // the lats node must point to the initial node + let last_index = linked_list_mem.len() - 1; + linked_list_mem[last_index] = Some(U256::from(OFFSET)); } pub fn to_vec(&self) -> Vec { // Include all keys. self.serialize_and_prune(self.kv_store.keys()) } +} +impl Display for Smt { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + for (key, val) in self.kv_store.iter().map(|(&key, &val)| (key2u(key), val)) { + write!(f, "({:?}, {:?})\n", key, val)?; + } + Ok(()) + } } fn serialize( @@ -516,7 +547,7 @@ fn serialize( } } -fn load_linked_list_data_with_key_and_bits( +fn _load_linked_list_data_with_key_and_bits( smt: &Smt, key: Key, cur_bits: Bits, @@ -542,30 +573,41 @@ fn load_linked_list_data_with_key_and_bits( // The last leaf must point to the new one. let len = linked_list_mem.len(); - linked_list_mem[len - 1] = Some(U256::from(O + len)); + linked_list_mem[len - 1] = Some(U256::from(OFFSET + len)); + log::debug!( + "setting linked_list_mem[{len} - 1] to {:?}", + U256::from(OFFSET + len) + ); // The nibbles are the address. linked_list_mem.push(Some(key2u(rem_key))); + log::debug!("setting linked_list_mem[{len}] to {:?}", key2u(rem_key)); // Set the value. linked_list_mem.push(Some(val)); + log::debug!("setting linked_list_mem[{len} + 1] to {:?}", val); // Set the original value. linked_list_mem.push(Some(val)); + log::debug!("setting linked_list_mem[{len} + 2] to {:?}", val); // Set the next node as the initial node. - linked_list_mem.push(Some(U256::from(O))); + linked_list_mem.push(Some(U256::from(OFFSET))); + log::debug!( + "setting linked_list_mem[{len} + 3] to {:?}", + U256::from(OFFSET) + ); // Put the pointer in state_ptrs - state_ptrs.insert(key2u(rem_key), O + len); + state_ptrs.insert(key2u(rem_key), OFFSET + len); } else { let key_left = Key(node.0[0..4].try_into().unwrap()); let key_right = Key(node.0[4..8].try_into().unwrap()); - load_linked_list_data_with_key_and_bits::<_, O>( + _load_linked_list_data_with_key_and_bits::<_, OFFSET>( smt, key_left, cur_bits.add_bit(false), linked_list_mem, state_ptrs, ); - load_linked_list_data_with_key_and_bits::<_, O>( + _load_linked_list_data_with_key_and_bits::<_, OFFSET>( smt, key_right, cur_bits.add_bit(true), From aabc15688f9cfc0d3b72f4a307c3d45d27d630c9 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Fri, 4 Oct 2024 17:52:51 +0200 Subject: [PATCH 12/60] Missing files --- .../core/create_type2_contract_account.asm | 63 +++ .../asm/linked_list/type2/final_tries.asm | 101 ++++ .../asm/linked_list/type2/initial_tries.asm | 56 +++ .../linked_list/type2/state_linked_list.asm | 468 ++++++++++++++++++ .../src/cpu/kernel/constants/smt_type.rs | 23 + 5 files changed, 711 insertions(+) create mode 100644 evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm create mode 100644 evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm create mode 100644 evm_arithmetization/src/cpu/kernel/constants/smt_type.rs diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm new file mode 100644 index 000000000..adbecd39b --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm @@ -0,0 +1,63 @@ +// Create a smart contract account with the given address and the given endowment value. +// Pre stack: address +// Post stack: status +%macro create_contract_account + // stack: address + DUP1 %insert_touched_addresses + DUP1 %append_created_contracts + POP + %read_code ISZERO %jumpi(%%add_account) + // Check that the nonce is 0. + // stack: address + DUP1 %nonce + // stack: nonce, address + %jumpi(%%error_collision) + // stack: address + // Check that the code is empty. + DUP1 %extcodehash + %eq_const(@EMPTY_STRING_POSEIDON_HASH) ISZERO %jumpi(%%error_collision) + DUP1 %balance + %jump(%%do_insert) + + %%add_account: + // stack: address + DUP1 PUSH 1 + // stack: is_contract, address, address + %journal_add_account_created + // stack: address + PUSH 0 + %%do_insert: + // stack: new_acct_value, address + // Write the new account's data to MPT data, and get a pointer to it. + // stack: new_acct_value, address + PUSH 0 DUP3 %journal_add_nonce_change + %stack (new_acct_value, address) -> (address, 1, new_acct_value, address) + %set_nonce // nonce = 1 + // stack: new_acct_value, address + DUP2 %set_balance // balance = new_acct_value + %stack (address) -> (address, @EMPTY_STRING_POSEIDON_HASH) + %set_code + // stack: empty + PUSH 0 // success + %jump(%%end) + +// If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. +// (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) +// So we return 1 to indicate an error. +%%error_collision: + %stack (address) -> (1) +%%end: + // stack: status +%endmacro + +%macro append_created_contracts + // stack: address + %mload_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN) + // stack: nb_created_contracts, address + SWAP1 DUP2 + // stack: nb_created_contracts, address, nb_created_contracts + %mstore_kernel(@SEGMENT_CREATED_CONTRACTS) + // stack: nb_created_contracts + %increment + %mstore_global_metadata(@GLOBAL_METADATA_CREATED_CONTRACTS_LEN) +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm new file mode 100644 index 000000000..06e48ba3a --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm @@ -0,0 +1,101 @@ +// Given a pointer `root_ptr` to the root of a trie, insert all the final nodes in +// the state_linked_list starting at `node_ptr_ptr`. +// Pre stack: node_ptr_ptr, root_ptr, retdest +// Post stack: new_root_ptr. // The value of new_root_ptr shouldn't change +global insert_all_final_nodes: + // stack: node_ptr_ptr, root_ptr, retdest + SWAP1 DUP2 + MLOAD_GENERAL + // stack: key, root_ptr, node_ptr_ptr, retdest + DUP3 + %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) + EQ + %jumpi(no_more_nodes) + // stack: key, root_ptr, node_ptr_ptr, retdest + PUSH after_smt_read + DUP2 + PUSH 64 + DUP5 + // stack: root_ptr, nibbles, key, after_smt_read, key, root_ptr, node_ptr_ptr, retdest + %jump(smt_read) +after_smt_read: + //stack: trie_value_ptr_ptr, key, root_ptr, node_ptr_ptr, retdest + DUP4 + %increment // Get the final value + SWAP1 + %mstore_trie_data + // stack: key, root_ptr, node_ptr_ptr, retdest + POP + SWAP1 + %next_node + // stack: node_ptr_ptr', root_ptr, retdest + %jump(insert_all_initial_nodes) + +no_more_nodes: + // stack: key, root_ptr, node_ptr_ptr, retdest + %stack (key, root_ptr, node_ptr_ptr, retdest) ->(retdest, root_ptr) + JUMP + +// Delete all the values in the final state linked list which where deleted from the initial state. +// Pre stack: node_ptr_ptr, root_ptr, retdest +// Post stack: new_root_ptr. +global delete_removed_nodes: + // stack: node_ptr_ptr, root_ptr, retdest + DUP1 + // We assume that the size of the initial state linked list, containing the nodes + // 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 initial state linked list was stored at and addresses smaller than `@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN`. + // If we also know that `@SEGMENT_ACCOUNT_LINKED_LIST <= node_ptr_ptr`, for deleting node at `node_ptr_ptr` it + // suffices to check that `node_ptr_ptr` != `@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN` + EQ + %jumpi(delete_removed_nodes_end) + // stack: node_ptr_ptr, root_ptr, retdest + DUP1 + %next_node + %eq_const(@U256_MAX) // If the next node pointer is @U256_MAX, the node was deleted + %jumpi(delete_node) + // stack: node_ptr_ptr, root_ptr, retdest + %next_initial_node + %jump(delete_removed_nodes) + +delete_removed_nodes_end: + // stack: account_ptr_ptr, root_ptr, retdest + %stack (node_ptr_ptr, root_ptr, retdest) -> (retdest, root_ptr) + JUMP + +delete_node: + // stack: node_ptr_ptr, root_ptr, retdest + DUP1 + MLOAD_GENERAL + %stack (key, node_ptr_ptr, root_ptr) -> (root_ptr, 64, key, after_mpt_delete, node_ptr_ptr) + %jump(mpt_delete) +after_mpt_delete: + // stack: root_ptr', node_ptr_ptr, retdest + SWAP1 + %next_initial_node + %jump(delete_removed_nodes) + + +global set_final_tries: + PUSH set_final_tries_after + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + %first_initial_node // Skip the first node. + %jump(delete_removed_nodes) +set_final_tries_after: + // stack: new_state_root + PUSH set_final_tries_after_after SWAP1 + // stack: new_state_root, set_final_tries_after_after + %first_node + %jump(insert_all_final_nodes) +set_final_tries_after_after: + //stack: new_state_root + %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + JUMP + +%macro set_final_tries + // stack: (empty) + PUSH %%after + %jump(set_final_tries) +%%after: +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm new file mode 100644 index 000000000..f9b82a7ee --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm @@ -0,0 +1,56 @@ + +global set_initial_state_trie: + // stack: retdest + PUSH set_initial_state_trie_after + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + %first_initial_node // Skip the first node. + %jump(insert_all_initial_nodes) +set_initial_state_trie_after: + //stack: new_state_root + %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) + JUMP + +%macro set_initial_state_trie + // stack: (empty) + PUSH %%after + %jump(set_initial_state_trie) +%%after: +%endmacro + +// Given a pointer `root_ptr` to the root of a trie, insert all the initial nodes in +// the state_linked_list starting at `node_ptr_ptr`. +// Pre stack: node_ptr_ptr, root_ptr, retdest +// Post stack: new_root_ptr. // The value of new_root_ptr shouldn't change +global insert_all_initial_nodes: + // stack: node_ptr_ptr, root_ptr, retdest + SWAP1 DUP2 + MLOAD_GENERAL + // stack: key, root_ptr, node_ptr_ptr, retdest + DUP3 + %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) + EQ + %jumpi(no_more_nodes) + // stack: key, root_ptr, node_ptr_ptr, retdest + PUSH after_smt_read + DUP2 + PUSH 64 + DUP5 + // stack: root_ptr, nibbles, key, after_smt_read, key, root_ptr, node_ptr_ptr, retdest + %jump(smt_read) +after_smt_read: + //stack: trie_value_ptr_ptr, key, root_ptr, node_ptr_ptr, retdest + DUP4 + %add_const(2) // Get the initial value + SWAP1 + %mstore_trie_data + // stack: key, root_ptr, node_ptr_ptr, retdest + POP + SWAP1 + %next_initial_node + // stack: node_ptr_ptr', root_ptr, retdest + %jump(insert_all_initial_nodes) + +no_more_nodes: + // stack: key, root_ptr, node_ptr_ptr, retdest + %stack (key, root_ptr, node_ptr_ptr, retdest) ->(retdest, root_ptr) + JUMP \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm new file mode 100644 index 000000000..44b60bcfb --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -0,0 +1,468 @@ +/// The state linked list is stored in SEGMENT_ACCOUNTS_LINKED_LIST in the kernel memory (context=0). +/// The length of the segment is stored in @GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE. +/// Searching and inserting is done by guessing the predecessor in the list. +/// If the key isn't found in the array, it is inserted +/// at the correct location. The linked list is used to keep track of +/// inserted, modified and deleted accounts balances, nonces, storage, etc, during the execution, so that the +/// initial and final MPT state tries can be reconstructed at the end of the execution. +/// An empty astate linked list is written as +/// [@U256_MAX, _, _, @SEGMENT_ACCOUNTS_LINKED_LIST] in SEGMENT_ACCOUNTS_LINKED_LIST. +/// Each node is encoded using 4 values: +/// - 0: The key +/// - 1: The value +/// - 2: The initial value. +/// - 3: A ptr (in segment @SEGMENT_ACCOUNTS_LINKED_LIST) to the next node in the list. + +%macro store_initial_state + PUSH %%after + %jump(store_initial_state) +%%after: +%endmacro + + +/// Iterates over the initial state linked list and copies the values in the inital values slot. +/// Computes the length of `SEGMENT_STORAGE_LINKED_LIST` and +/// checks against `GLOBAL_METADATA_STORAGE_LINKED_LIST_NEXT_AVAILABLE`. +/// It also checks that the next node address is current address + 4 +/// and that all keys are strictly increasing. +/// NOTE: It may be more efficient to check that the next node addres != U256_MAX +/// (i.e. node was not deleted) and ensure that no node with repeated key +/// is ever read. +global store_initial_state: + // stack: retdest + PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + ADD + // stack: cur_len, retdest + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + DUP1 + MLOAD_GENERAL + // stack: current_key, current_node_ptr, cur_len, retdest + %assert_eq_const(@U256_MAX) + + // stack: current_node_ptr, cur_len', retdest + DUP1 + %next_node + // stack: next_node_ptr, current_node_ptr, cur_len, retdest + DUP1 + SWAP2 + %next_initial_node + %assert_eq(store_initial_state_end) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, cur_len', retdest + +loop_store_initial_state: +global debug_loop: + // stack: current_node_ptr, cur_len, retdest + DUP1 + %increment + MLOAD_GENERAL + // stack: value, current_node_ptr, cur_len, retdest + DUP2 + %add_const(@STATE_COPY_PAYLOAD_PTR) + // stack: cpy_value_ptr, value, current_node_ptr, cur_len, retdest + SWAP1 + MSTORE_GENERAL // Store cpy_value + // stack: current_node_ptr, cur_len, retdest + SWAP1 PUSH @STATE_LINKED_LISTS_NODE_SIZE + ADD + SWAP1 + // Check correctness of next node ptr and strict key monotonicity. + DUP1 + MLOAD_GENERAL + // stack: current_key, current_node_ptr, cur_len', retdest + SWAP1 + DUP1 + %next_node + // stack: next_node_ptr, current_node_ptr, current_key, cur_len', retdest + DUP1 + SWAP2 + %next_initial_node + %assert_eq(store_initial_state_end_pop_key) // next_node_ptr == current_node_ptr + node_size + // stack: next_node_ptr, current_key, cur_len', retdest + SWAP1 + DUP2 +global debug_loading: + MLOAD_GENERAL +global debug_este_es_el_problema_baby: + %assert_gt // next_key > current_key + // stack: next_node_ptr, cur_len', retdest + %jump(loop_store_initial_state) + +store_initial_state_end_pop_key: + // stack: next_node_ptr, current_key, cur_len', retdest + SWAP1 POP + +store_initial_state_end: + // stack: next_node_ptr, cur_len', retdest + %assert_eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + + // stack: cur_len, retdest + DUP1 + %mstore_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + JUMP + + +// 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_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. +%macro get_valid_state_ptr + // stack: ptr/4 + // Check that the pointer is greater than the segment. + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + DUP2 + %mul_const(4) + // stack: ptr, @SEGMENT_ACCOUNTS_LINKED_LIST, ptr/4 + %increment %assert_gt + // stack: ptr/4 + DUP1 + PUSH 4 + %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 + // stack: @SEGMENT_ACCOUNTS_LINKED_LIST/4 + accounts_linked_list_len/4, ptr/4, ptr/4 + %assert_gt + %mul_const(4) +%endmacro + +%macro set_nonce + // stack: address, nonce + %key_nonce + %insert_key + // stack: (empty) +%endmacro + +%macro set_balance + // stack: address, balance + %key_balance + %insert_key + // stack: (empty) +%endmacro + +%macro set_code + // stack: address, code + %key_code + %insert_key + // stack: (empty) +%endmacro + +%macro set_code_length + // stack: address, code_lenght + %key_code_length + %insert_key + // stack: (empty) +%endmacro + + +%macro insert_slot + // stack: addr, slot, value + %addr_to_state_key + %key_storage + %insert_key + // stack: (empty) +%endmacro + +%macro insert_slot_from_addr_key + // stack: addr_key, slot_key, value + %key_storage + %insert_key + // stack: (empty) +%endmacro + + +%macro insert_key + %stack (key, value) -> (key, value, %%after) + %jump(insert_key) + %%after: +%endmacro + +/// Inserts the pair `(key, value)` into the linked list if `key` was not already present, +/// or modifies the vealue if it was already present. +global insert_key: + // stack: key, value, retdest + PROVER_INPUT(linked_list::insert_state) + // stack: pred_ptr/4, key, value, retdest + %get_valid_state_ptr + + // stack: pred_ptr, key, value, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_key, pred_key, pred_ptr, key, value, retdest + DUP4 + GT + DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // we need to insert a new node. + %jumpi(insert_new_key) + // stack: pred_key, pred_ptr, key, value, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 + %assert_eq + // stack: pred_ptr, key, value, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, key_found_with_overwrite) + // The key is not in the list. + PANIC + +key_found_with_overwrite: + // The key was already in the list + // stack: pred_ptr, key, value, retdest + // Load the payload pointer + %increment + // stack: payload_ptr_ptr, key, value, retdest + DUP3 MSTORE_GENERAL + %pop2 + JUMP + +insert_new_key: + // stack: pred_key, pred_ptr, key, value, retdest + POP + // get the value of the next address + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + // stack: next_ptr_ptr, key, value, retdest + %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + DUP2 + MLOAD_GENERAL + // stack: next_ptr, new_ptr, next_ptr_ptr, key, value, retdest + // Check that this is not a deleted node + DUP1 + %eq_const(@U256_MAX) + %assert_zero + DUP1 + MLOAD_GENERAL + // stack: next_key, next_ptr, new_ptr, next_ptr_ptr, key, value, retdest + DUP5 + // Here, (key > pred_key) || (pred_ptr == @SEGMENT_ACCOUNTS_LINKED_LIST). + // We should have (key < next_key), meaning the new value can be inserted between pred_ptr and next_ptr. + %assert_lt + // stack: next_ptr, new_ptr, next_ptr_ptr, key, value, retdest + SWAP2 + DUP2 + // stack: new_ptr, next_ptr_ptr, new_ptr, next_ptr, key, value, retdest + MSTORE_GENERAL + // stack: new_ptr, next_ptr, key, value, retdest + DUP1 + DUP4 + MSTORE_GENERAL + // stack: new_ptr, next_ptr, key, value, retdest + %increment + DUP1 + DUP5 + MSTORE_GENERAL + // stack: new_ptr + 1, next_ptr, key, value, retdest + %add_const(2) // TODO: We're skiping the initial value. This shuould also done with the accounts bc this value should't be used. + DUP1 + // stack: new_next_ptr, new_next_ptr, next_ptr, key, value, retdest + SWAP2 + MSTORE_GENERAL + // stack: new_next_ptr, key, value, retdest + %increment + %mstore_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + // stack: key, value, retdest + %pop2 + JUMP + + +/// Searches the key in the state the linked list. If the key is stored +/// returns the current value of the key, or 0 otherwise. +global search_key: + // stack: key, retdest + PROVER_INPUT(linked_list::search_state) + // stack: pred_ptr/4, key, retdest + %get_valid_state_ptr + + // stack: pred_ptr, key, retdest + DUP1 + MLOAD_GENERAL + DUP1 + // stack: pred_key, pred_key, pred_ptr, key, retdest + DUP4 + GT + DUP3 %eq_const(@SEGMENT_ACCOUNTS_LINKED_LIST) + ADD // OR + // If the predesessor is strictly smaller or the predecessor is the special + // node with key @U256_MAX (and hence we're inserting a new minimum), then + // the key was not found. + %jumpi(key_not_found) + // stack: pred_addr_key, pred_ptr, addr_key, key, retdest + // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. + DUP3 +global debug_fail_1: + %assert_eq + // stack: pred_ptr, key, retdest + // Check that this is not a deleted node + DUP1 + %add_const(@STATE_NEXT_NODE_PTR) + MLOAD_GENERAL + %jump_neq_const(@U256_MAX, key_found) + // The key is not in the list. + +global debug_fail_2: + PANIC + +key_found: + // The key was already in the list. + // stack: pred_ptr, key, retdest + %increment + MLOAD_GENERAL + // stack: value, key, retdest + %stack (value, key, retdest) -> (retdest, value) + JUMP + +key_not_found: + // stack: pred_key, pred_ptr, key, retdest + %stack (pred_key, pred_ptr, key, retdest) -> (retdest, 0) + JUMP + +%macro search_key + %stack (key) -> (key, %%after) + %jump(search_key) +%%after: + // stack: value +%endmacro +%macro search_slot_from_addr_key + // stack: addr_key, slot + %key_storage + %search_key +%endmacro + +%macro read_balance + // stack: addr_key + %key_balance + %search_key +%endmacro + +%macro read_code + // stack: addr_key + %key_code + %search_key + // stack: code_hash +%endmacro + +%macro read_code_length + // stack: addr_key + %key_code_length + %search_key + // stack: code_length +%endmacro + +%macro read_nonce + // stack: addr_key + %key_nonce + %search_key + // stack: nonce +%endmacro + +%macro remove_key + PUSH %%after + SWAP1 + %jump(remove_key) +%%after: +%endmacro + +%macro remove_balance + %key_balance + %remove_key +%endmacro + +%macro remove_slot_from_addr_key + %key_storage + %remove_key +%endmacro + +/// Removes the key and its value from the state linked list. +/// Panics if the key is not in the list. +global remove_key: + // stack: key, retdest + PROVER_INPUT(linked_list::remove_slot) + // stack: pred_ptr/4, key, retdest + %get_valid_state_ptr + // stack: pred_ptr, key, retdest + %add_const(@STATE_NEXT_NODE_PTR) + // stack: next_ptr_ptr, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_ptr, next_ptr_ptr, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_key, next_ptr, next_ptr_ptr, key, retdest + DUP4 + %assert_eq + // stack: next_ptr, next_ptr_ptr, key, retdest + %add_const(@STATE_NEXT_NODE_PTR) + // stack: next_next_ptr_ptr, next_ptr_ptr, key, retdest + DUP1 + MLOAD_GENERAL + // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, key, retdest + SWAP1 + %mstore_u256_max + // stack: next_next_ptr, next_ptr_ptr, key, retdest + MSTORE_GENERAL + POP + JUMP + +%macro read_slot_from_current_addr + // stack: slot + %address + %addr_to_state_key + %key_storage + %stack (storage_key) -> (storage_key, %%after) + // stack: storage_key, %%after + %jump(search_key) +%%after: + // stack: slot_value +%endmacro + +%macro read_slot_from_addr_key + // stack: state_key, slot + %slot_to_storage_key + %stack (storage_key) -> (storage_key, %%after) + %jump(search_key) +%%after: + // stack: slot_value +%endmacro + +%macro read_slot_from_addr + // stack: address, slot + %addr_to_state_key + %key_storage + %stack (storage_key) -> (storage_key, %%after) + // stack: storage_key, %%after + %jump(search_key) +%%after: + // stack: slot_value +%endmacro + +%macro first_node + // stack: empty + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + %next_node +%endmacro + +%macro first_initial_node + // stack: empty + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + %next_initial_node +%endmacro + +%macro next_node + // stack: node_ptr + %add_const(@ACCOUNTS_NEXT_NODE_PTR) + MLOAD_GENERAL + // stack: next_node_ptr +%endmacro + +%macro next_initial_node + // stack: node_ptr + %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) + // stack: next_node_ptr +%endmacro \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/constants/smt_type.rs b/evm_arithmetization/src/cpu/kernel/constants/smt_type.rs new file mode 100644 index 000000000..b134598bc --- /dev/null +++ b/evm_arithmetization/src/cpu/kernel/constants/smt_type.rs @@ -0,0 +1,23 @@ +#[derive(Copy, Clone, Debug)] +pub(crate) enum PartialSmtType { + Hash = 0, + Internal = 1, + Leaf = 2, +} + +impl PartialSmtType { + pub(crate) const COUNT: usize = 3; + + pub(crate) fn all() -> [Self; Self::COUNT] { + [Self::Hash, Self::Internal, Self::Leaf] + } + + /// The variable name that gets passed into kernel assembly code. + pub(crate) fn var_name(&self) -> &'static str { + match self { + Self::Hash => "SMT_NODE_HASH", + Self::Internal => "SMT_NODE_INTERNAL", + Self::Leaf => "SMT_NODE_LEAF", + } + } +} From e06d051934fdbd53b9dc246f856ab96b58cb87d9 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 9 Oct 2024 23:54:50 +0200 Subject: [PATCH 13/60] Fix erc20 up to hashing final tries --- .../src/cpu/kernel/asm/account_code.asm | 35 ++++++++++++++- .../src/cpu/kernel/asm/balance.asm | 2 +- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 13 ++++-- .../src/cpu/kernel/asm/core/nonce.asm | 21 +++++---- .../src/cpu/kernel/asm/core/process_txn.asm | 8 ++++ .../cpu/kernel/asm/core/selfdestruct_list.asm | 4 +- .../cpu/kernel/asm/core/touched_addresses.asm | 10 ++++- .../kernel/asm/core/transfer_cdk_erigon.asm | 43 ++++++++++--------- .../src/cpu/kernel/asm/core/util.asm | 8 ++-- .../linked_list/type2/state_linked_list.asm | 12 +++--- .../asm/mpt/hash/hash_trie_specific.asm | 1 + evm_arithmetization/src/generation/mod.rs | 9 +++- .../src/generation/prover_input.rs | 35 ++++++++++++++- evm_arithmetization/src/generation/state.rs | 35 ++++++++++++++- evm_arithmetization/src/witness/transition.rs | 7 ++- evm_arithmetization/tests/erc20_type2.rs | 2 +- 16 files changed, 188 insertions(+), 57 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 8853e953a..463d22ec5 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -42,7 +42,7 @@ global extcodehash: { global extcodehash: // stack: address, retdest - %read_code %mload_trie_data + %read_code // stack: codehash, retdest SWAP1 JUMP } @@ -110,7 +110,10 @@ load_code_ctd: // stack: codehash, ctx, retdest DUP1 ISZERO %jumpi(load_code_non_existent_account) // Load the code non-deterministically in memory and return the length. +global debug_account_code: PROVER_INPUT(account_code) +#[cfg(feature = eth_mainnet)] +{ %stack (code_size, codehash, ctx, retdest) -> (ctx, code_size, codehash, retdest, code_size) // Check that the hash of the loaded code equals `codehash`. // ctx == DST, as SEGMENT_CODE == offset == 0. @@ -119,6 +122,11 @@ load_code_ctd: %assert_eq // stack: retdest, code_size JUMP +} +#[cfg(feature = cdk_erigon)] +{ + %jump(poseidon_hash_code) +} load_code_non_existent_account: // Write 0 at address 0 for soundness: SEGMENT_CODE == 0, hence ctx == addr. @@ -149,3 +157,28 @@ load_code_padded_ctd: MSTORE_GENERAL // stack: retdest, code_size JUMP + +#[cfg(feature = cdk_erigon)] +{ + global poseidon_hash_code: + // stack: padded_code_size, codehash, ctx, retdest + // %stack (padded_code_size, codehash, ctx) -> (0, 0, padded_code_size, ctx, codehash) + %stack (padded_code_size, codehash, ctx) -> (ctx, padded_code_size, codehash, padded_code_size, ctx) + POSEIDON_GENERAL + %assert_eq + // stack: padded_code_size, ctx, retdest + %decrement + remove_padding_loop: + // stack: offset, ctx, retdest + DUP2 DUP2 ADD DUP1 MLOAD_GENERAL + // stack: code[offset], offset+ctx, offset, ctx, retdest + SWAP1 PUSH 0 MSTORE_GENERAL + // stack: code[offset], offset, ctx, retdest + %and_const(1) %jumpi(remove_padding_after) + // stack: offset, ctx, retdest + %decrement %jump(remove_padding_loop) + + remove_padding_after: + %stack (offset, ctx, retdest) -> (retdest, offset) + JUMP +} diff --git a/evm_arithmetization/src/cpu/kernel/asm/balance.asm b/evm_arithmetization/src/cpu/kernel/asm/balance.asm index 32e8e84ec..3e4e1711d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/balance.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/balance.asm @@ -41,7 +41,7 @@ global balance: #[cfg(feature = cdk_erigon)] { // stack: address, retdest - %read_balance %mload_trie_data + %read_balance // stack: balance, retdest SWAP1 JUMP } diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index e3d78206f..8e11cc495 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -19,14 +19,16 @@ global update_scalable_block_number: // stack: last_block_slot, block_number, retdest %write_scalable_storage // stack: retdest - +global debug_wtf_is_happening_with_retdest: // Check timestamp PUSH @TIMESTAMP_STORAGE_POS PUSH @ADDRESS_SCALABLE_L2_STATE_KEY %read_slot_from_addr_key // stack: old_timestamp, retdest %timestamp - GT %jumpi(update_scalable_timestamp) + GT +global debug_before_jumpi: + %jumpi(update_scalable_timestamp) global update_scalable_prev_block_root_hash: // stack: retdest @@ -97,23 +99,28 @@ global create_scalable_l2_account: // stack: (empty) PUSH update_scalable_block_number // stack: retdest - // stack: new_account_ptr, retdest PUSH 0 PUSH @ADDRESS_SCALABLE_L2_STATE_KEY %set_nonce + // stack: retdest PUSH 0 PUSH @ADDRESS_SCALABLE_L2_STATE_KEY %set_balance // balance + // stack: retdest PUSH @EMPTY_STRING_HASH PUSH @ADDRESS_SCALABLE_L2_STATE_KEY %set_codehash // code hash + // stack: retdest PUSH 0 PUSH @ADDRESS_SCALABLE_L2_STATE_KEY %set_code_length // code_length + // stack: retdest + JUMP + %macro write_scalable_storage // stack: slot, value PUSH @ADDRESS_SCALABLE_L2_STATE_KEY diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm index 93085e97d..61a02fa10 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm @@ -58,23 +58,21 @@ global increment_nonce: // stack: address, retdest DUP1 %read_nonce - // stack: nonce_ptr, address, retdest + // stack: nonce, address, retdest DUP1 ISZERO %jumpi(create_nonce) - // stack: nonce_ptr, address, retdest - DUP1 %mload_trie_data - // stack: nonce, nonce_ptr, address, retdest - DUP1 DUP4 %journal_add_nonce_change - // stack: nonce, nonce_ptr, address, retdest + // stack: nonce, address, retdest + // stack: nonce, address, retdest + DUP1 DUP3 %journal_add_nonce_change + // stack: nonce, address, retdest %increment SWAP1 - // stack: nonce_ptr, nonce', address, retdest - %mstore_trie_data - // stack: address, retdest - POP + // stack: address, nonce', retdest + %set_nonce + // stack: retdest JUMP create_nonce: - // stack: nonce_ptr, address, retdest + // stack: nonce, address, retdest POP // stack: address, retdest PUSH 0 DUP2 %journal_add_nonce_change @@ -82,6 +80,7 @@ global increment_nonce: PUSH 1 SWAP1 %set_nonce + JUMP } diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 6a006ef71..f50cef72b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -40,6 +40,7 @@ global process_normalized_txn: // stack: sender, retdest // Assert sender balance >= gas_limit * gas_price + value. +global debug_balance: %balance // stack: sender_balance, retdest %mload_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS) @@ -221,6 +222,7 @@ global process_contract_creation_txn_after_constructor: // stack: leftover_gas', new_ctx, address, retdest, success, leftover_gas SWAP5 POP %delete_all_touched_addresses +global debug_jump_to_delete_all_1: %delete_all_selfdestructed_addresses // stack: new_ctx, address, retdest, success, leftover_gas POP @@ -313,10 +315,12 @@ process_message_txn_after_call_contd: %pay_coinbase_and_refund_sender // stack: leftover_gas', new_ctx, retdest, success, leftover_gas SWAP4 POP +global debug_delete_all_touched: %delete_all_touched_addresses %delete_all_selfdestructed_addresses // stack: new_ctx, retdest, success, leftover_gas POP +global debug_y_salta_salta_salta: JUMP process_message_txn_fail: @@ -463,6 +467,7 @@ create_contract_account_fault: %pay_coinbase_and_refund_sender // stack: leftover_gas', retdest %delete_all_touched_addresses +global debug_jump_to_delete_all_3: %delete_all_selfdestructed_addresses // stack: leftover_gas', retdest SWAP1 PUSH 0 // success @@ -476,6 +481,7 @@ contract_creation_fault_3: %pay_coinbase_and_refund_sender // stack: leftover_gas', retdest, success %delete_all_touched_addresses +global debug_jump_to_delete_all_5: %delete_all_selfdestructed_addresses %stack (leftover_gas, retdest, success) -> (retdest, 0, leftover_gas) JUMP @@ -488,6 +494,7 @@ contract_creation_fault_3_zero_leftover: // stack: leftover_gas, retdest, success %pay_coinbase_and_refund_sender %delete_all_touched_addresses +global debug_jump_to_delete_all_6: %delete_all_selfdestructed_addresses %stack (leftover_gas, retdest, success) -> (retdest, 0, leftover_gas) JUMP @@ -500,6 +507,7 @@ contract_creation_fault_4: // stack: leftover_gas, retdest, success %pay_coinbase_and_refund_sender %delete_all_touched_addresses +global debug_jump_to_delete_all_7: %delete_all_selfdestructed_addresses %stack (leftover_gas, retdest, success) -> (retdest, 0, leftover_gas) JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm b/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm index 05e158c34..e72263908 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm @@ -72,7 +72,9 @@ bingo: %increment %jump(delete_all_selfdestructed_addresses_loop) delete_all_selfdestructed_addresses_done: // stack: i, len, retdest - %pop2 JUMP + %pop2 +global debug_jump_from_delete_all: + JUMP %macro delete_all_selfdestructed_addresses %stack () -> (%%after) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm b/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm index a8e926e77..8d5e097db 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm @@ -86,22 +86,28 @@ global delete_all_touched_addresses: PUSH @SEGMENT_TOUCHED_ADDRESSES ADD PUSH @SEGMENT_TOUCHED_ADDRESSES delete_all_touched_addresses_loop: +global debug_lobeando: // `i` and `len` are both scaled by SEGMENT_TOUCHED_ADDRESSES // stack: i, len, retdest DUP2 DUP2 EQ %jumpi(delete_all_touched_addresses_done) // stack: i, len, retdest DUP1 MLOAD_GENERAL // stack: loaded_addr, i, len, retdest - DUP1 %is_empty %jumpi(bingo) + DUP1 +global debug_loaded_addr: + %is_empty %jumpi(bingo) // stack: loaded_addr, i, len, retdest POP %increment %jump(delete_all_touched_addresses_loop) bingo: +global debug_bingo: // stack: loaded_addr, i, len, retdest %delete_account %increment %jump(delete_all_touched_addresses_loop) delete_all_touched_addresses_done: // stack: i, len, retdest - %pop2 JUMP + %pop2 +global debug_chaito_noma: + JUMP %macro delete_all_touched_addresses %stack () -> (%%after) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm b/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm index d1ee78c01..579542096 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/transfer_cdk_erigon.asm @@ -31,28 +31,27 @@ global deduct_eth: DUP1 %insert_touched_addresses DUP2 ISZERO %jumpi(deduct_eth_noop) DUP1 %read_balance - // stack: balance_ptr, addr, amount, retdest - DUP1 %mload_trie_data - // stack: balance, balance_ptr, addr, amount, retdest - DUP1 DUP5 GT - // stack: amount > balance, balance, balance_ptr, addr, amount, retdest + // stack: balance, addr, amount, retdest + // stack: balance, addr, amount, retdest + DUP1 DUP4 GT + // stack: amount > balance, balance, addr, amount, retdest %jumpi(deduct_eth_insufficient_balance) - // stack: balance, balance_ptr, addr, amount, retdest - DUP1 DUP5 EQ - // stack: amount == balance, balance, balance_ptr, addr, amount, retdest + // stack: balance, addr, amount, retdest + DUP1 DUP4 EQ + // stack: amount == balance, balance, addr, amount, retdest %jumpi(deduct_eth_delete_balance) - %stack (balance, balance_ptr, addr, amount, retdest) -> (balance, amount, balance_ptr, retdest, 0) + %stack (balance, addr, amount, retdest) -> (balance, amount, addr, retdest, 0) SUB SWAP1 - // stack: balance_ptr, balance - amount, retdest, 0 - %mstore_trie_data + // stack: addr, balance - amount, retdest, 0 + %set_balance // stack: retdest, 0 JUMP deduct_eth_insufficient_balance: - %stack (balance, balance_ptr, addr, amount, retdest) -> (retdest, 1) + %stack (balance, addr, amount, retdest) -> (retdest, 1) JUMP deduct_eth_delete_balance: - %stack (balance, balance_ptr, addr, amount, retdest) -> (addr, retdest, 0) + %stack (balance, addr, amount, retdest) -> (addr, retdest, 0) %remove_balance // stack: retdest, 0 JUMP @@ -74,20 +73,22 @@ global add_eth: DUP1 %insert_touched_addresses DUP2 ISZERO %jumpi(add_eth_noop) // stack: addr, amount, retdest - DUP1 %read_code %mload_trie_data + DUP1 %read_code // stack: codehash, addr, amount, retdest ISZERO %jumpi(add_eth_new_account) // If the account is empty, we need to create the account. // stack: addr, amount, retdest - %key_balance DUP1 %search_key // TODO: replace with read_balance? + %key_balance + // stack: key_balance, amount + DUP1 %search_key // TODO: replace with read_balance? DUP1 ISZERO %jumpi(add_eth_zero_balance) - %stack (balance_ptr, key_balance, amount) -> (balance_ptr, amount, balance_ptr) - // stack: balance_ptr, amount, balance_ptr, retdest - %mload_trie_data ADD - // stack: balance+amount, balance_ptr, retdest - SWAP1 %mstore_trie_data + %stack (balance, key_balance, amount) -> (balance, amount, key_balance) + // stack: balance, amount, key_balance, retdest + ADD + // stack: balance+amount, key_balance, retdest + SWAP1 %insert_key JUMP add_eth_zero_balance: - // stack: balance_ptr, key_balance, amount, retdest + // stack: balance, key_balance, amount, retdest POP // stack: key_balance, amount, retdest %insert_key // TODO: replace with set_balance? diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index 8dcb730d8..a8e83bc03 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -80,7 +80,7 @@ #[cfg(feature = cdk_erigon)] { // stack: addr - DUP1 %read_nonce %mload_trie_data + DUP1 %read_nonce // stack: nonce, addr ISZERO %not_bit } @@ -95,7 +95,7 @@ #[cfg(feature = cdk_erigon)] { // stack: addr - DUP1 %read_nonce %mload_trie_data + DUP1 %read_nonce // stack: nonce, addr ISZERO %not_bit } @@ -109,7 +109,7 @@ #[cfg(feature = cdk_erigon)] { // stack: addr - DUP1 %read_balance %mload_trie_data + DUP1 %read_balance // stack: balance, addr ISZERO %not_bit } @@ -124,7 +124,7 @@ #[cfg(feature = cdk_erigon)] { // stack: addr - %read_code %mload_trie_data + %read_code // stack: codehash %eq_const(@EMPTY_STRING_POSEIDON_HASH) } diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index 44b60bcfb..2ec9534e0 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -51,7 +51,6 @@ global store_initial_state: // stack: next_node_ptr, cur_len', retdest loop_store_initial_state: -global debug_loop: // stack: current_node_ptr, cur_len, retdest DUP1 %increment @@ -81,9 +80,7 @@ global debug_loop: // stack: next_node_ptr, current_key, cur_len', retdest SWAP1 DUP2 -global debug_loading: MLOAD_GENERAL -global debug_este_es_el_problema_baby: %assert_gt // next_key > current_key // stack: next_node_ptr, cur_len', retdest %jump(loop_store_initial_state) @@ -278,7 +275,9 @@ global search_key: // stack: key, retdest PROVER_INPUT(linked_list::search_state) // stack: pred_ptr/4, key, retdest +global debug_pred_ptr_p_4: %get_valid_state_ptr +global debug_pred_ptr: // stack: pred_ptr, key, retdest DUP1 @@ -293,7 +292,7 @@ global search_key: // node with key @U256_MAX (and hence we're inserting a new minimum), then // the key was not found. %jumpi(key_not_found) - // stack: pred_addr_key, pred_ptr, addr_key, key, retdest + // stack: pred_key, pred_ptr, key, retdest // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. DUP3 global debug_fail_1: @@ -319,8 +318,10 @@ key_found: JUMP key_not_found: +global debug_key_not_found: // stack: pred_key, pred_ptr, key, retdest %stack (pred_key, pred_ptr, key, retdest) -> (retdest, 0) +global debug_o_margot: JUMP %macro search_key @@ -413,7 +414,6 @@ global remove_key: %macro read_slot_from_current_addr // stack: slot %address - %addr_to_state_key %key_storage %stack (storage_key) -> (storage_key, %%after) // stack: storage_key, %%after @@ -424,7 +424,7 @@ global remove_key: %macro read_slot_from_addr_key // stack: state_key, slot - %slot_to_storage_key + %key_storage %stack (storage_key) -> (storage_key, %%after) %jump(search_key) %%after: 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 31fa192fa..36c7048f2 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 @@ -150,6 +150,7 @@ global encode_txn: %build_kernel_address SWAP1 // stack: DST, SRC, txn_rlp_len, txn_rlp_len, rlp_addr, new_len, retdest +global debug_por_aca_se_copian_lost_bits: %memcpy_bytes ADD // stack new_rlp_addr, new_len, retdest diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 7f6aec906..8b3393133 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -96,7 +96,10 @@ pub struct GenerationInputs { /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. + #[cfg(feature = "eth_mainnet")] pub contract_code: HashMap>, + #[cfg(feature = "cdk_erigon")] + pub contract_code: HashMap>, /// Information contained in the block header. pub block_metadata: BlockMetadata, @@ -148,7 +151,10 @@ pub struct TrimmedGenerationInputs { /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. + #[cfg(feature = "eth_mainnet")] pub contract_code: HashMap>, + #[cfg(feature = "cdk_erigon")] + pub contract_code: HashMap>, /// Information contained in the block header. pub block_metadata: BlockMetadata, @@ -242,7 +248,8 @@ impl GenerationInputs { } #[cfg(feature = "cdk_erigon")] { - state_root = H256::from_uint(&hash_serialize_u256(&self.tries.state_trie.to_vec()).into()); + state_root = + H256::from_uint(&hash_serialize_u256(&self.tries.state_trie.to_vec()).into()); } TrimmedGenerationInputs { diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index f76bc3009..604d8fe63 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -234,6 +234,7 @@ impl GenerationState { /// Initializes the code segment of the given context with the code /// corresponding to the provided hash. /// Returns the length of the code. + #[cfg(feature = "eth_mainnet")] fn run_account_code(&mut self) -> Result { // stack: codehash, ctx, ... let codehash = stack_peek(self, 0)?; @@ -251,6 +252,36 @@ impl GenerationState { } Ok(code.len().into()) } + #[cfg(feature = "cdk_erigon")] + fn run_account_code(&mut self) -> Result { + // stack: codehash, ctx, ... + let codehash = stack_peek(self, 0)?; + let context = stack_peek(self, 1)? >> CONTEXT_SCALING_FACTOR; + let context = u256_to_usize(context)?; + let mut address = MemoryAddress::new(context, Segment::Code, 0); + let code = self + .inputs + .contract_code + .get(&codehash) + .ok_or(ProgramError::ProverInputError(CodeHashNotFound))?; + let code_len = code.len(); + + for &byte in code { + self.memory.set(address, byte.into()); + address.increment(); + } + + // Padding + self.memory.set(address, 1.into()); + let mut len = code_len + 1; + len = 56 * ((len + 55) / 56); + let last_byte_addr = MemoryAddress::new(context, Segment::Code, len - 1); + let mut last_byte = u256_to_usize(self.memory.get_with_init(last_byte_addr))?; + last_byte |= 0x80; + self.memory.set(last_byte_addr, last_byte.into()); + + Ok(len.into()) + } // Bignum modular multiplication. // On the first call, calculates the remainder and quotient of the given inputs. @@ -378,7 +409,7 @@ impl GenerationState { "state ll = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) ); - log::debug!("state btree = {:?}", self.state_pointers); + log::debug!("state btree = {:#?}", self.state_pointers); log::debug!("input state = {}", self.inputs.trimmed_tries.state_trie); match input_fn.0[1].as_str() { @@ -570,7 +601,7 @@ impl GenerationState { )?, ); } - Ok(U256::from(pred_key / ACCOUNTS_LINKED_LIST_NODE_SIZE)) + Ok(U256::from(pred_ptr / ACCOUNTS_LINKED_LIST_NODE_SIZE)) } /// Returns an unscaled pointer to a node in the list such that diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 2c9e9cbc8..da4eb8e93 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -27,6 +27,8 @@ use crate::keccak_sponge::keccak_sponge_stark::KeccakSpongeOp; use crate::memory::segments::Segment; #[cfg(feature = "cdk_erigon")] use crate::poseidon::poseidon_stark::PoseidonOp; +#[cfg(feature = "cdk_erigon")] +use smt_trie::code::hash_bytecode_u256; use crate::util::u256_to_usize; use crate::witness::errors::ProgramError; use crate::witness::memory::MemoryChannel::GeneralPurpose; @@ -568,8 +570,13 @@ impl GenerationState { self.observe_address(tip_h160); } else if dst == KERNEL.global_labels["observe_new_contract"] { let tip_u256 = stack_peek(self, 0)?; - let tip_h256 = H256::from_uint(&tip_u256); - self.observe_contract(tip_h256)?; + #[cfg(feature = "eth_mainnet")] + { + let tip_h256 = H256::from_uint(&tip_u256); + self.observe_contract(tip_h256)?; + } + #[cfg(feature = "cdk_erigon")] + self.observe_contract(tip_u256)?; } Ok(()) @@ -585,6 +592,7 @@ impl GenerationState { /// Observe the given code hash and store the associated code. /// When called, the code corresponding to `codehash` should be stored in /// the return data. + #[cfg(feature = "eth_mainnet")] pub(crate) fn observe_contract(&mut self, codehash: H256) -> Result<(), ProgramError> { if self.inputs.contract_code.contains_key(&codehash) { return Ok(()); // Return early if the code hash has already been @@ -607,6 +615,29 @@ impl GenerationState { Ok(()) } + #[cfg(feature = "cdk_erigon")] + pub(crate) fn observe_contract(&mut self, codehash: U256) -> Result<(), ProgramError> { + if self.inputs.contract_code.contains_key(&codehash) { + return Ok(()); // Return early if the code hash has already been + // observed. + } + + let ctx = self.registers.context; + let returndata_offset = ContextMetadata::ReturndataSize.unscale(); + let returndata_size_addr = + MemoryAddress::new(ctx, Segment::ContextMetadata, returndata_offset); + let returndata_size = u256_to_usize(self.memory.get_with_init(returndata_size_addr))?; + let code = self.memory.contexts[ctx].segments[Segment::Returndata.unscale()].content + [..returndata_size] + .iter() + .map(|x| x.unwrap_or_default().low_u32() as u8) + .collect::>(); + debug_assert_eq!(hash_bytecode_u256(code.clone()), codehash); + + self.inputs.contract_code.insert(codehash, code); + + Ok(()) + } pub(crate) fn rollback(&mut self, checkpoint: GenerationStateCheckpoint) { self.registers = checkpoint.registers; diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index ee0d858ce..57c561142 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -330,7 +330,12 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o // ), // ); - assert!(pc < KERNEL.code.len(), "Kernel PC is out of range: {}", pc); + assert!( + pc < KERNEL.code.len(), + "Kernel PC is out of range: {} while KERNEL len is {}", + pc, + KERNEL.code.len() + ); } pub(crate) trait Transition: State diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index 0ec3b70ab..bd8d67ed1 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -113,7 +113,7 @@ fn test_erc20() -> anyhow::Result<()> { }; let contract_code = [giver_bytecode(), token_bytecode(), vec![]] - .map(|v| (keccak(v.clone()), v)) + .map(|v| (hash_bytecode_u256(v.clone()), v)) .into(); let expected_smt_after: Smt = { From 652927048d842f58bed0ef4c76e60e0d5f595fb6 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Mon, 14 Oct 2024 15:06:24 +0200 Subject: [PATCH 14/60] Fix initial smt hash in erc20 --- .../src/cpu/kernel/aggregator.rs | 4 +- .../asm/linked_list/type2/initial_tries.asm | 13 +++-- .../src/cpu/kernel/asm/main.asm | 14 +++-- .../src/cpu/kernel/asm/smt/hash.asm | 5 ++ .../src/cpu/kernel/asm/smt/read.asm | 12 +++++ evm_arithmetization/src/generation/mod.rs | 3 +- .../src/generation/prover_input.rs | 8 ++- evm_arithmetization/src/generation/state.rs | 9 +++- evm_arithmetization/src/witness/transition.rs | 9 +++- smt_trie/src/smt.rs | 53 ++++++++++++++----- 10 files changed, 107 insertions(+), 23 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index b4ff8118f..ae5fe8634 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 158 + 159 } else { // unreachable 0 @@ -173,6 +173,8 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/shift.asm"), include_str!("asm/signed.asm"), #[cfg(feature = "cdk_erigon")] + include_str!("asm/smt/hash.asm"), + #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/keys.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/utils.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm index f9b82a7ee..7f3204b7c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm @@ -28,19 +28,26 @@ global insert_all_initial_nodes: // stack: key, root_ptr, node_ptr_ptr, retdest DUP3 %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) +global debug_check_no_more_nodes: EQ %jumpi(no_more_nodes) // stack: key, root_ptr, node_ptr_ptr, retdest PUSH after_smt_read DUP2 - PUSH 64 - DUP5 - // stack: root_ptr, nibbles, key, after_smt_read, key, root_ptr, node_ptr_ptr, retdest +global before_split_key: + %split_key +global after_split_key: + // stack: k0, k1, k2, k3, after_smt_read, key, root_ptr, node_ptr_ptr, retdest + PUSH 0 + DUP8 + // stack: root_ptr, level, k0, k1, k2, k3, after_smt_read, key, root_ptr, node_ptr_ptr, retdest %jump(smt_read) after_smt_read: +global debug_after_smt_read: //stack: trie_value_ptr_ptr, key, root_ptr, node_ptr_ptr, retdest DUP4 %add_const(2) // Get the initial value + MLOAD_GENERAL SWAP1 %mstore_trie_data // stack: key, root_ptr, node_ptr_ptr, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 2d25a6612..c0f3ac690 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -224,13 +224,21 @@ global check_state_trie: %set_initial_state_trie // stack: trie_data_len - PUSH @INITIAL_RLP_ADDR - // stack: rlp_start, trie_data_len - %mpt_hash_state_trie + #[cfg(feature = eth_mainnet)] + { + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, trie_data_len + %mpt_hash_state_trie + } + #[cfg(feature = cdk_erigon)] + { + %smt_hash_state + } // stack: init_state_hash, trie_data_len // Check that the initial trie is correct. %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_BEFORE) +global debug_check_initial_trie: %assert_eq // Check that the stored trie data length is correct. %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm index 08dbfd1a1..f4142e75d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm @@ -28,6 +28,7 @@ smt_hash_unknown_node_type: PANIC smt_hash_hash: +global debug_hash_hash: // stack: node, node_ptr, cur_len, retdest POP // stack: node_ptr, cur_len, retdest @@ -40,6 +41,7 @@ smt_hash_hash: JUMP smt_hash_internal: +global hash_internal: // stack: node, node_ptr, cur_len, retdest POP // stack: node_ptr, cur_len, retdest @@ -51,6 +53,7 @@ smt_hash_internal: %stack (left_child_ptr, node_ptr_plus_1, cur_len, retdest) -> (left_child_ptr, cur_len, smt_hash_internal_after_left, node_ptr_plus_1, retdest) %jump(smt_hash) smt_hash_internal_after_left: +global debug_hash_internal_after_left: %stack (left_hash, cur_len, node_ptr_plus_1, retdest) -> (node_ptr_plus_1, left_hash, cur_len, retdest) %increment // stack: node_ptr+2, left_hash, cur_len, retdest @@ -58,12 +61,14 @@ smt_hash_internal_after_left: %stack (right_child_ptr, left_hash, cur_len, retdest) -> (right_child_ptr, cur_len, smt_hash_internal_after_right, left_hash, retdest) %jump(smt_hash) smt_hash_internal_after_right: +global debug_hash_internal_after_right: %stack (right_hash, cur_len, left_hash) -> (left_hash, right_hash, 0, cur_len) POSEIDON %stack (hash, cur_len, retdest) -> (retdest, hash, cur_len) JUMP smt_hash_leaf: +global debug_hash_leaf: // stack: node_ptr, cur_len, retdest SWAP1 %add_const(3) SWAP1 // stack: node_ptr, cur_len, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm index cd4bce33d..31934afaf 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm @@ -38,6 +38,7 @@ global smt_read: PANIC smt_read_hash: +global debug_smt_read_hash: // stack: node_type, node_payload_ptr, level, ks, retdest POP // stack: node_payload_ptr, level, ks, retdest @@ -47,10 +48,12 @@ smt_read_hash: PANIC // Trying to read a non-empty hash node. Should never happen. smt_read_empty: +global debug_smt_read_empty: %stack (level, k0, k1, k2, k3, retdest) -> (retdest, 0) JUMP smt_read_internal: +global debug_smt_read_internal: // stack: node_type, node_payload_ptr, level, ks, retdest POP // stack: node_payload_ptr, level, ks, retdest @@ -62,25 +65,30 @@ smt_read_internal: DUP1 %eq_const(3) %jumpi(smt_read_internal_3) PANIC smt_read_internal_0: +global debug_smt_read_internal_0: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k0, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk0, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, newk0, k1, k2, k3 ) %jump(smt_read_internal_contd) smt_read_internal_1: +global debug_smt_read_internal_1: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k1, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk1, node_payload_ptr, level , k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, newk1, k2, k3 ) %jump(smt_read_internal_contd) smt_read_internal_2: +global debug_smt_read_internal_2: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k2, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk2, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, newk2, k3 ) %jump(smt_read_internal_contd) smt_read_internal_3: +global debug_smt_read_internal_3: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k3, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk3, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, k2, newk3 ) smt_read_internal_contd: +global debug_smt_read_contd: // stack: bit, node_payload_ptr, level, k0, k1, k2, k3, retdest ADD // stack: child_ptr_ptr, level, k0, k1, k2, k3, retdest @@ -91,6 +99,7 @@ smt_read_internal_contd: %jump(smt_read) smt_read_leaf: +global debug_smt_read_leaf: // stack: node_payload_ptr, level, ks, retdest DUP1 %mload_trie_data // stack: rem_key, node_payload_ptr, level, ks, retdest @@ -100,11 +109,14 @@ smt_read_leaf: %stack (value_ptr, rem_key, level, k0, k1, k2, k3) -> (k0, k1, k2, k3, rem_key, value_ptr) %combine_key // stack: this_rem_key, rem_key, value_ptr, retdest +global debug_pffff: EQ %jumpi(smt_read_existing_leaf) smt_read_non_existing_leaf: +global debug_smt_read_non_existing_leaf: %stack (value_ptr, retdest) -> (retdest, 0) JUMP smt_read_existing_leaf: +global debug_smt_existing_leaf: // stack: value_ptr, retdest SWAP1 JUMP diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 8b3393133..975f031ee 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -248,8 +248,9 @@ impl GenerationInputs { } #[cfg(feature = "cdk_erigon")] { + let smt_data = self.tries.state_trie.to_vec(); state_root = - H256::from_uint(&hash_serialize_u256(&self.tries.state_trie.to_vec()).into()); + H256::from_uint(&hash_serialize_u256(&smt_data).into()); } TrimmedGenerationInputs { diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 604d8fe63..d61d1de04 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -117,10 +117,16 @@ impl GenerationState { #[cfg(feature = "cdk_erigon")] { n = Ok(new_content.len()); - let mut smt_data = self.inputs.trimmed_tries.state_trie.to_vec(); + let mut smt_data = self + .inputs + .trimmed_tries + .state_trie + .to_vec_skip_empty_node_and_add_offset(new_content.len()); + log::debug!("smt bef = {:?}", smt_data); if smt_data.len() == 2 { smt_data.extend([U256::zero(); 2]); } + log::debug!("initial smt = {:?}", smt_data); let smt_data = smt_data.into_iter().map(|x| Some(x)); new_content.extend(smt_data); self.memory.insert_preinitialized_segment( diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index da4eb8e93..862c4ba23 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -15,7 +15,7 @@ use crate::byte_packing::byte_packing_stark::BytePackingOp; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::stack::MAX_USER_STACK_SIZE; -use crate::generation::linked_list::{empty_list_mem, STATE_LINKED_LIST_NODE_SIZE}; +use crate::generation::linked_list::{empty_list_mem, StateLinkedList, STATE_LINKED_LIST_NODE_SIZE}; #[cfg(feature = "eth_mainnet")] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; use crate::generation::mpt::{load_receipts_mpt, load_transactions_mpt}; @@ -196,6 +196,12 @@ pub(crate) trait State { let mut running = true; let mut final_clock = 0; + let mem = self + .get_generation_state() + .memory + .get_preinit_memory(Segment::AccountsLinkedList); + log::debug!("initial state linked list = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList)); + loop { let registers = self.get_registers(); let pc = registers.program_counter; @@ -481,6 +487,7 @@ impl GenerationState { let withdrawal_prover_inputs = all_withdrawals_prover_inputs_reversed(&inputs.withdrawals); let ger_prover_inputs = all_ger_prover_inputs(inputs.ger_data); let bignum_modmul_result_limbs = Vec::new(); + log::debug!("smt trie = {:?}", inputs.tries.state_trie); #[cfg(feature = "eth_mainnet")] { diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 57c561142..d86aa71bb 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -11,6 +11,7 @@ use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::stack::{ EQ_STACK_BEHAVIOR, IS_ZERO_STACK_BEHAVIOR, JUMPI_OP, JUMP_OP, MIGHT_OVERFLOW, STACK_BEHAVIORS, }; +use crate::generation::linked_list::StateLinkedList; use crate::generation::state::State; use crate::memory::segments::Segment; use crate::witness::errors::ProgramError; @@ -307,7 +308,13 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o state.get_generation_state().stack(), ), ); - + if KERNEL.offset_name(pc) == "insert_all_initial_nodes" { + let mem = state + .get_generation_state() + .memory + .get_preinit_memory(Segment::AccountsLinkedList); + log::debug!("state linked list = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList)); + } // state.log( // level, // format!( diff --git a/smt_trie/src/smt.rs b/smt_trie/src/smt.rs index 9240596c5..76b27ca09 100644 --- a/smt_trie/src/smt.rs +++ b/smt_trie/src/smt.rs @@ -408,6 +408,7 @@ impl Smt { /// Serialize and prune the SMT into a vector of U256. /// Starts with a [0, 0] for convenience, that way `ptr=0` is a canonical /// empty node. Therefore the root of the SMT is at `ptr=2`. + /// TODO: this convention changes with "hashing in the end". /// `keys` is a list of keys whose prefixes will not be hashed-out in the /// serialization. /// Serialization rules: @@ -419,8 +420,9 @@ impl Smt { pub fn serialize_and_prune, I: IntoIterator>( &self, keys: I, - ) -> Vec { - let mut v = vec![U256::zero(); 2]; // For empty hash node. + v: &mut Vec, + offset: usize, + ) { let key = Key(self.root.elements); let mut keys_to_include = HashSet::new(); @@ -435,11 +437,10 @@ impl Smt { } } - serialize(self, key, &mut v, Bits::empty(), &keys_to_include); + serialize(self, key, v, Bits::empty(), &keys_to_include, offset); if v.len() == 2 { v.extend([U256::zero(); 2]); } - v } pub fn load_linked_list_data( @@ -481,7 +482,16 @@ impl Smt { pub fn to_vec(&self) -> Vec { // Include all keys. - self.serialize_and_prune(self.kv_store.keys()) + let mut v = vec![U256::zero(); 2]; // For empty hash node. + self.serialize_and_prune(self.kv_store.keys(), &mut v, 0); + v + } + + pub fn to_vec_skip_empty_node_and_add_offset(&self, offset: usize) -> Vec { + // Include all keys. + let mut v = vec![]; // No empty hash node. + self.serialize_and_prune(self.kv_store.keys(), &mut v, offset); + v } } @@ -500,6 +510,7 @@ fn serialize( v: &mut Vec, cur_bits: Bits, keys_to_include: &HashSet, + offset: usize, ) -> usize { if key.0.iter().all(F::is_zero) { return 0; // `ptr=0` is an empty node. @@ -509,7 +520,11 @@ fn serialize( let index = v.len(); v.push(HASH_TYPE.into()); v.push(key2u(key)); - index + if index == 0 { // Empty hash node is at the beggining of the segment + index + } else { + index + offset + } } else if let Some(node) = smt.db.get_node(&key) { if node.0.iter().all(F::is_zero) { panic!("wtf?"); @@ -526,7 +541,7 @@ fn serialize( v.push(LEAF_TYPE.into()); v.push(key2u(rem_key)); v.push(val); - index + index + offset } else { let key_left = Key(node.0[0..4].try_into().unwrap()); let key_right = Key(node.0[4..8].try_into().unwrap()); @@ -534,13 +549,27 @@ fn serialize( v.push(INTERNAL_TYPE.into()); v.push(U256::zero()); v.push(U256::zero()); - let i_left = - serialize(smt, key_left, v, cur_bits.add_bit(false), keys_to_include).into(); + let i_left = serialize( + smt, + key_left, + v, + cur_bits.add_bit(false), + keys_to_include, + offset, + ) + .into(); v[index + 1] = i_left; - let i_right = - serialize(smt, key_right, v, cur_bits.add_bit(true), keys_to_include).into(); + let i_right = serialize( + smt, + key_right, + v, + cur_bits.add_bit(true), + keys_to_include, + offset, + ) + .into(); v[index + 2] = i_right; - index + index + offset } } else { unreachable!() From 33f29db920f8259f0b39422e23548daedf7ddc72 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 15 Oct 2024 09:49:56 +0200 Subject: [PATCH 15/60] Fix trie data size --- evm_arithmetization/src/cpu/kernel/asm/main.asm | 2 ++ evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm | 4 +++- evm_arithmetization/src/generation/prover_input.rs | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index c0f3ac690..8bba0f572 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -218,6 +218,7 @@ global check_state_trie: %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) PROVER_INPUT(trie_ptr::trie_data_size) +global debug_storing_trie_data_size: %mstore_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) // stack: trie_data_len @@ -242,6 +243,7 @@ global debug_check_initial_trie: %assert_eq // Check that the stored trie data length is correct. %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) +global debug_trie_data_length: %assert_eq // We set a dummy value as an initial trie data length, diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm index f4142e75d..a11f06d69 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm @@ -32,7 +32,9 @@ global debug_hash_hash: // stack: node, node_ptr, cur_len, retdest POP // stack: node_ptr, cur_len, retdest + DUP1 ISZERO %jumpi(empty_hash_node) // We don't count empty hash nodes SWAP1 %add_const(2) SWAP1 +empty_hash_node: // stack: node_ptr, cur_len, retdest %increment // stack: node_ptr+1, cur_len, retdest @@ -41,7 +43,7 @@ global debug_hash_hash: JUMP smt_hash_internal: -global hash_internal: +global debug_hash_internal: // stack: node, node_ptr, cur_len, retdest POP // stack: node_ptr, cur_len, retdest diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index d61d1de04..8633e86ce 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -127,6 +127,7 @@ impl GenerationState { smt_data.extend([U256::zero(); 2]); } log::debug!("initial smt = {:?}", smt_data); + log::debug!("smt len = {:?}", smt_data.len()); let smt_data = smt_data.into_iter().map(|x| Some(x)); new_content.extend(smt_data); self.memory.insert_preinitialized_segment( From 946c09acaabff89637d192debb2b49e1e0129258 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 15 Oct 2024 09:49:56 +0200 Subject: [PATCH 16/60] Fix set_final_tries --- .../src/cpu/kernel/aggregator.rs | 4 +- .../asm/linked_list/type2/final_tries.asm | 37 ++++++++++--------- .../src/cpu/kernel/asm/main.asm | 18 +++++++-- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index ae5fe8634..feb592c66 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 159 + 160 } else { // unreachable 0 @@ -175,6 +175,8 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/hash.asm"), #[cfg(feature = "cdk_erigon")] + include_str!("asm/smt/insert.asm"), + #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/keys.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/smt/utils.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm index 06e48ba3a..5a9b50ab4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm @@ -7,29 +7,29 @@ global insert_all_final_nodes: SWAP1 DUP2 MLOAD_GENERAL // stack: key, root_ptr, node_ptr_ptr, retdest - DUP3 - %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) - EQ + DUP1 + %eq_const(@U256_MAX) %jumpi(no_more_nodes) // stack: key, root_ptr, node_ptr_ptr, retdest - PUSH after_smt_read - DUP2 - PUSH 64 - DUP5 - // stack: root_ptr, nibbles, key, after_smt_read, key, root_ptr, node_ptr_ptr, retdest - %jump(smt_read) -after_smt_read: - //stack: trie_value_ptr_ptr, key, root_ptr, node_ptr_ptr, retdest + PUSH after_smt_insert DUP4 %increment // Get the final value - SWAP1 - %mstore_trie_data - // stack: key, root_ptr, node_ptr_ptr, retdest - POP - SWAP1 + MLOAD_GENERAL + // stack: value, after_smt_insert, key, root_ptr, node_ptr_ptr, retdest + DUP3 + %split_key + // stack: k0, k1, k2, k3, value, after_smt_insert, key, root_ptr, node_ptr_ptr, retdest + PUSH 0 + DUP9 + // stack: root_ptr, level, k0, k1, k2, k3, after_smt_insert, key, root_ptr, node_ptr_ptr, retdest + %jump(smt_insert) +after_smt_insert: +global debug_after_smt_insert: + //stack: root_ptr', key, root_ptr, node_ptr_ptr, retdest + %stack (new_root_ptr, key, root_ptr, next_node_ptr_ptr) -> (next_node_ptr_ptr, new_root_ptr) %next_node - // stack: node_ptr_ptr', root_ptr, retdest - %jump(insert_all_initial_nodes) + // stack: node_ptr_ptr', root_ptr', retdest + %jump(insert_all_final_nodes) no_more_nodes: // stack: key, root_ptr, node_ptr_ptr, retdest @@ -65,6 +65,7 @@ delete_removed_nodes_end: JUMP delete_node: +global debug_delete_node: // stack: node_ptr_ptr, root_ptr, retdest DUP1 MLOAD_GENERAL diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 8bba0f572..363ca53ee 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -251,9 +251,21 @@ global debug_trie_data_length: PUSH 1 global check_final_state_trie: %set_final_tries - PUSH @INITIAL_RLP_ADDR - // stack: rlp_start, dummy_trie_len - %mpt_hash_state_trie %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) %assert_eq + + #[cfg(feature = eth_mainnet)] + { + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, dummy_trie_len + %mpt_hash_state_trie + } + #[cfg(feature = cdk_erigon)] + { + %smt_hash_state + } + + %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) +global debug_final_trie_hash: + %assert_eq // We don't need the trie data length here. POP From 7fc95cb243ad0a950e29480b8debdaad0d1b30d4 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 15 Oct 2024 16:06:56 +0200 Subject: [PATCH 17/60] Fix erc20 but constraints are failing --- .../linked_list/type2/state_linked_list.asm | 1 - .../src/cpu/kernel/asm/main.asm | 7 +-- evm_arithmetization/src/witness/transition.rs | 44 +++++++++++++++++-- evm_arithmetization/tests/erc20_type2.rs | 3 ++ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index 2ec9534e0..1dd8b6688 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -156,7 +156,6 @@ store_initial_state_end: %macro insert_slot // stack: addr, slot, value - %addr_to_state_key %key_storage %insert_key // stack: (empty) diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 363ca53ee..0ff1dce64 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -134,10 +134,11 @@ global start_txns: } #[cfg(feature = cdk_erigon)] { + // TODO: Uncomment // If txn_idx == 0, perform pre-state execution for CDK erigon. - %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) - ISZERO - %jumpi(pre_block_execution) + //%mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) + //ISZERO + //%jumpi(pre_block_execution) } // stack: init_gas_used, txn_counter, num_nibbles, txn_nb diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index d86aa71bb..14de01f8c 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -1,3 +1,4 @@ +use ethereum_types::U256; use log::log_enabled; use plonky2::field::types::Field; use plonky2::hash::hash_types::RichField; @@ -6,6 +7,7 @@ use super::util::stack_pop_with_log_and_fill; use crate::cpu::columns::CpuColumnsView; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; +use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::opcodes::get_opcode; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::stack::{ @@ -14,6 +16,8 @@ use crate::cpu::stack::{ use crate::generation::linked_list::StateLinkedList; use crate::generation::state::State; use crate::memory::segments::Segment; +// TO REMOVE! +use crate::util::u256_to_usize; use crate::witness::errors::ProgramError; use crate::witness::gas::gas_to_charge; use crate::witness::memory::MemoryAddress; @@ -310,10 +314,42 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ); if KERNEL.offset_name(pc) == "insert_all_initial_nodes" { let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::AccountsLinkedList); - log::debug!("state linked list = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList)); + .get_generation_state() + .memory + .get_preinit_memory(Segment::AccountsLinkedList); + log::debug!( + "state linked list = {:?}", + StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + ); + } + + if KERNEL.offset_name(pc) == "smt_hash_state" { + let mem = state + .get_generation_state() + .memory + .get_preinit_memory(Segment::AccountsLinkedList); + log::debug!( + "state linked list = {:?}", + StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + ); + let root_ptr = u256_to_usize( + state + .get_generation_state() + .memory + .read_global_metadata(GlobalMetadata::StateTrieRoot), + ) + .unwrap(); + let mem = state + .get_generation_state() + .memory + .get_preinit_memory(Segment::TrieData); + log::debug!( + "state smt data = {:?}", + mem[root_ptr..] + .iter() + .map(|x| x.unwrap_or_default()) + .collect::>() + ); } // state.log( // level, diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index bd8d67ed1..15ec5b92d 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -174,6 +174,9 @@ fn test_erc20() -> anyhow::Result<()> { } .into(); + log::debug!("expected smt after = {}", expected_smt_after); + log::debug!("expected smt data after = {:?}", expected_smt_after.to_vec()); + let trie_roots_after = TrieRoots { state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), transactions_root: transactions_trie.hash(), From 007a6ab8d6b6b8b447caa0243516fd1c1ba67699 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 16 Oct 2024 14:11:25 +0200 Subject: [PATCH 18/60] Fix CTLs --- evm_arithmetization/src/cpu/cpu_stark.rs | 10 ++++++++-- evm_arithmetization/src/witness/operation.rs | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/evm_arithmetization/src/cpu/cpu_stark.rs b/evm_arithmetization/src/cpu/cpu_stark.rs index a0dd45e1e..77aad7f55 100644 --- a/evm_arithmetization/src/cpu/cpu_stark.rs +++ b/evm_arithmetization/src/cpu/cpu_stark.rs @@ -498,7 +498,10 @@ pub(crate) fn ctl_poseidon_general_input() -> TableWithColumns { let len = Column::single(COL_MAP.mem_channels[1].value[0]); let num_channels = F::from_canonical_usize(NUM_CHANNELS); - let timestamp = Column::linear_combination([(COL_MAP.clock, num_channels)]); + let timestamp = Column::linear_combination_with_constant( + [(COL_MAP.clock, num_channels)], + F::ONE - num_channels, + ); TableWithColumns::new( *Table::Cpu, @@ -539,7 +542,10 @@ pub(crate) fn ctl_poseidon_general_output() -> TableWithColumns { let mut columns = Vec::new(); columns.extend(Column::singles_next_row(COL_MAP.mem_channels[0].value)); let num_channels = F::from_canonical_usize(NUM_CHANNELS); - columns.push(Column::linear_combination([(COL_MAP.clock, num_channels)])); + columns.push(Column::linear_combination_with_constant( + [(COL_MAP.clock, num_channels)], + F::ONE - num_channels, + )); TableWithColumns::new(*Table::Cpu, columns, ctl_poseidon_general_filter()) } diff --git a/evm_arithmetization/src/witness/operation.rs b/evm_arithmetization/src/witness/operation.rs index 55f3d3c18..8818aa025 100644 --- a/evm_arithmetization/src/witness/operation.rs +++ b/evm_arithmetization/src/witness/operation.rs @@ -242,11 +242,13 @@ pub(crate) fn generate_poseidon_general>( let poseidon_op = PoseidonOp::PoseidonGeneralOp(PoseidonGeneralOp { base_address, - timestamp: clock * NUM_CHANNELS, + timestamp: clock * NUM_CHANNELS + 1, input: input.clone(), len: input.len(), }); + log::debug!("pushign poseding op = {:?}", poseidon_op); + let hash = hashout2u(poseidon_hash_padded_byte_vec(input.clone())); push_no_write(generation_state, hash); From be1955d7c2380d4f6234de9255cedb63b3fd18da Mon Sep 17 00:00:00 2001 From: hratoanina Date: Wed, 16 Oct 2024 09:11:40 -0400 Subject: [PATCH 19/60] Fix memory constraint --- evm_arithmetization/src/memory/memory_stark.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/memory/memory_stark.rs b/evm_arithmetization/src/memory/memory_stark.rs index 718cc45e3..357e72095 100644 --- a/evm_arithmetization/src/memory/memory_stark.rs +++ b/evm_arithmetization/src/memory/memory_stark.rs @@ -186,7 +186,7 @@ pub(crate) fn generate_first_change_flags_and_rc( ); row.preinitialized_segments_aux = (next_segment - - F::from_canonical_usize(Segment::StorageLinkedList.unscale())) + - F::from_canonical_usize(Segment::AccountsLinkedList.unscale())) * (next_segment - F::from_canonical_usize(Segment::StorageLinkedList.unscale())); row.preinitialized_segments = (next_segment From 8a165d5a648bcf9a419c425c7cfe0f11c4380df4 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 16 Oct 2024 15:23:10 +0200 Subject: [PATCH 20/60] [WIP] Adding scalable data final erc20 smt --- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 2 ++ .../src/cpu/kernel/asm/main.asm | 7 ++--- evm_arithmetization/tests/erc20_type2.rs | 29 ++++++++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index 8e11cc495..c721f3e7a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -15,6 +15,7 @@ global pre_block_execution: global update_scalable_block_number: // stack: retdest %blocknumber +global debug_blocknumber: PUSH @LAST_BLOCK_STORAGE_POS // stack: last_block_slot, block_number, retdest %write_scalable_storage @@ -90,6 +91,7 @@ skip_and_exit: global update_scalable_timestamp: // stack: retdest %timestamp +global debug_le_timestamp: PUSH @TIMESTAMP_STORAGE_POS // stack: timestamp_slot, timestamp, retdest %write_scalable_storage diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 0ff1dce64..363ca53ee 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -134,11 +134,10 @@ global start_txns: } #[cfg(feature = cdk_erigon)] { - // TODO: Uncomment // If txn_idx == 0, perform pre-state execution for CDK erigon. - //%mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) - //ISZERO - //%jumpi(pre_block_execution) + %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) + ISZERO + %jumpi(pre_block_execution) } // stack: init_gas_used, txn_counter, num_nibbles, txn_nb diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index 15ec5b92d..a49a38954 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -11,6 +11,7 @@ use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; #[cfg(feature = "eth_mainnet")] use evm_arithmetization::testing_utils::beacon_roots_contract_from_storage; +use evm_arithmetization::testing_utils::ADDRESS_SCALABLE_L2; use evm_arithmetization::testing_utils::{ beacon_roots_account_nibbles, create_account_storage, init_logger, preinitialized_state_and_storage_tries, sd2u, update_beacon_roots_account_storage, @@ -138,6 +139,13 @@ fn test_erc20() -> anyhow::Result<()> { &token_storage_after(), ); + set_account( + &mut smt, + ADDRESS_SCALABLE_L2, + &scalable_account(), + &HashMap::new(), + ); + smt }; @@ -175,7 +183,10 @@ fn test_erc20() -> anyhow::Result<()> { .into(); log::debug!("expected smt after = {}", expected_smt_after); - log::debug!("expected smt data after = {:?}", expected_smt_after.to_vec()); + log::debug!( + "expected smt data after = {:?}", + expected_smt_after.to_vec() + ); let trie_roots_after = TrieRoots { state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), @@ -259,6 +270,14 @@ fn token_storage_after() -> HashMap { storage } +fn scalable_storage_aftert() -> HashMap { + let mut storage = HashMap::new(); + storage.insert( + U256::from(LAST_BLOCK_STORAGE_POS), + +; ) +} + fn giver_account() -> AccountRlp { let code = giver_bytecode(); let len = code.len(); @@ -289,6 +308,14 @@ fn sender_account() -> AccountRlp { } } +fn scalable_account() -> AccountRlp { + AccountRlp { + nonce: 0.into(), + balance: 0.into(), + ..Default::default() + } +} + fn signed_tx() -> Vec { hex!("02f88701800a0a830142c594e7f1725e7734ce288f8367e1bb143e90bb3f051280a4a52c101e0000000000000000000000000000000000000000000000056bc75e2d63100000c001a0303f5591159d7ea303faecb1c8bd8624b55732f769de28b111190dfb9a7c5234a019d5d6d38938dc1c63acbe106cf361672def773ace4ca587860117d057326627").into() } From 136d2df3e8f13fe31e787c5eed682a98e9d68317 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 17 Oct 2024 14:26:18 +0200 Subject: [PATCH 21/60] Dont store 0s in create_scalable_l2_account --- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 25 ++++------- .../src/cpu/kernel/asm/core/create.asm | 16 +++++-- evm_arithmetization/tests/erc20_type2.rs | 42 ++++++++++++++++--- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index c721f3e7a..ee535f0f4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -23,10 +23,11 @@ global debug_blocknumber: global debug_wtf_is_happening_with_retdest: // Check timestamp PUSH @TIMESTAMP_STORAGE_POS - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY + PUSH @ADDRESS_SCALABLE_L2 %read_slot_from_addr_key // stack: old_timestamp, retdest %timestamp +global debug_el_timestamp: GT global debug_before_jumpi: %jumpi(update_scalable_timestamp) @@ -101,31 +102,21 @@ global create_scalable_l2_account: // stack: (empty) PUSH update_scalable_block_number // stack: retdest - PUSH 0 - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY - %set_nonce - - // stack: retdest - PUSH 0 - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY - %set_balance // balance + // Since nonce, balance and code length are 0 we only need to set + // the code hash // stack: retdest PUSH @EMPTY_STRING_HASH - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY - %set_codehash // code hash - - // stack: retdest - PUSH 0 - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY - %set_code_length // code_length + PUSH @ADDRESS_SCALABLE_L2 +global debug_setting_scalable_code: + %set_code // code hash // stack: retdest JUMP %macro write_scalable_storage // stack: slot, value - PUSH @ADDRESS_SCALABLE_L2_STATE_KEY + PUSH @ADDRESS_SCALABLE_L2 // stack: state_key, slot, value %insert_slot_from_addr_key // stack: (empty) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index c1c2e0d5b..b9aaee758 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -269,14 +269,22 @@ global set_codehash: { // stack: addr, codehash, retdest DUP1 %insert_touched_addresses - DUP1 %read_code %mload_trie_data + DUP1 + global debug_reading_code: + %read_code // stack: prev_codehash, addr, codehash, retdest - DUP2 %read_code_length %mload_trie_data + DUP2 + global debug_reading_code_length: + %read_code_length %stack (prev_code_length, prev_codehash, addr) -> (addr, prev_codehash, prev_code_length, addr) %journal_add_code_change // Add the code change to the journal. // stack: addr, codehash, retdest - DUP2 DUP2 %set_code - %returndatasize DUP2 %set_code_length + DUP2 DUP2 + global debug_setting_code: + %set_code + %returndatasize DUP2 + global debug_setting_code_lenght: + %set_code_length // stack: addr, codehash, retdest %pop2 JUMP } diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index a49a38954..71c9e48cd 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -12,6 +12,9 @@ use evm_arithmetization::prover::testing::prove_all_segments; #[cfg(feature = "eth_mainnet")] use evm_arithmetization::testing_utils::beacon_roots_contract_from_storage; use evm_arithmetization::testing_utils::ADDRESS_SCALABLE_L2; +use evm_arithmetization::testing_utils::LAST_BLOCK_STORAGE_POS; +use evm_arithmetization::testing_utils::STATE_ROOT_STORAGE_POS; +use evm_arithmetization::testing_utils::TIMESTAMP_STORAGE_POS; use evm_arithmetization::testing_utils::{ beacon_roots_account_nibbles, create_account_storage, init_logger, preinitialized_state_and_storage_tries, sd2u, update_beacon_roots_account_storage, @@ -25,6 +28,8 @@ use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; +use plonky2::field::types::PrimeField64; +use plonky2::hash::hash_types::RichField; use plonky2::plonk::config::KeccakGoldilocksConfig; use plonky2::util::timing::TimingTree; use smt_trie::code::hash_bytecode_u256; @@ -89,6 +94,8 @@ fn test_erc20() -> anyhow::Result<()> { &token_storage(), ); + let state_smt_before_root = state_smt_before.root; + let tries_before = TrieInputs { state_trie: state_smt_before, transactions_trie: HashedPartialTrie::from(Node::Empty), @@ -143,7 +150,7 @@ fn test_erc20() -> anyhow::Result<()> { &mut smt, ADDRESS_SCALABLE_L2, &scalable_account(), - &HashMap::new(), + &scalable_storage_after(&block_metadata, hashout2u(state_smt_before_root)), ); smt @@ -182,6 +189,11 @@ fn test_erc20() -> anyhow::Result<()> { } .into(); + let kb = key_code_length(ADDRESS_SCALABLE_L2); + log::debug!( + "scalable code length key = {:?}", + U256(std::array::from_fn(|i| kb.0[i].to_canonical_u64())) + ); log::debug!("expected smt after = {}", expected_smt_after); log::debug!( "expected smt data after = {:?}", @@ -270,12 +282,17 @@ fn token_storage_after() -> HashMap { storage } -fn scalable_storage_aftert() -> HashMap { +fn scalable_storage_after(block: &BlockMetadata, state_root_before: U256) -> HashMap { let mut storage = HashMap::new(); - storage.insert( - U256::from(LAST_BLOCK_STORAGE_POS), - -; ) + storage.insert(U256::from(LAST_BLOCK_STORAGE_POS.1), block.block_number); + storage.insert(U256::from(TIMESTAMP_STORAGE_POS.1), block.block_timestamp); + + let mut arr = [0; 64]; + (block.block_number - U256::one()).to_big_endian(&mut arr[0..32]); + U256::from(STATE_ROOT_STORAGE_POS.1).to_big_endian(&mut arr[32..64]); + let slot = keccak(arr); + storage.insert(slot.into_uint(), state_root_before); + storage } fn giver_account() -> AccountRlp { @@ -338,9 +355,22 @@ fn set_account( account: &AccountRlp, storage: &HashMap, ) { + let key = key_balance(addr); + log::debug!( + "setting {:?} balance to {:?}, the key is {:?}", + addr, + account.balance, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); smt.set(key_balance(addr), account.balance); smt.set(key_nonce(addr), account.nonce); smt.set(key_code(addr), h2u(account.code_hash)); + let key = key_code_length(addr); + log::debug!( + "setting {:?} code length, the key is {:?}", + addr, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); smt.set(key_code_length(addr), account.code_length); for (&k, &v) in storage { smt.set(key_storage(addr, k), v); From 461f77873e4f623daee4d235af3588b50d902e2a Mon Sep 17 00:00:00 2001 From: hratoanina Date: Mon, 21 Oct 2024 04:13:21 -0400 Subject: [PATCH 22/60] Adapt linked_list structs --- .../src/cpu/kernel/constants/global_metadata.rs | 2 +- evm_arithmetization/src/cpu/kernel/interpreter.rs | 13 ++++--------- .../src/cpu/kernel/tests/mpt/linked_list.rs | 5 ----- evm_arithmetization/src/generation/linked_list.rs | 4 ++++ 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs b/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs index 6c8d339dd..ec94ddbf5 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/global_metadata.rs @@ -119,7 +119,7 @@ pub(crate) enum GlobalMetadata { } impl GlobalMetadata { - pub(crate) const COUNT: usize = 56; + pub(crate) const COUNT: usize = 55; /// Unscales this virtual offset by their respective `Segment` value. pub(crate) const fn unscale(&self) -> usize { diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 8bb498acc..088750665 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -22,7 +22,7 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::generation::debug_inputs; use crate::generation::linked_list::LinkedListsPtrs; -use crate::generation::mpt::{load_linked_lists_and_txn_and_receipt_mpts, TrieRootPtrs}; +use crate::generation::mpt::TrieRootPtrs; use crate::generation::rlp::all_rlp_prover_inputs_reversed; use crate::generation::state::{ all_ger_prover_inputs, all_withdrawals_prover_inputs_reversed, GenerationState, @@ -234,14 +234,9 @@ impl Interpreter { // Set state's inputs. We trim unnecessary components. self.generation_state.inputs = inputs.trim(); - // Initialize the MPT's pointers. - let (trie_root_ptrs, state_leaves, storage_leaves, trie_data) = - load_linked_lists_and_txn_and_receipt_mpts( - &mut self.generation_state.state_ptrs.accounts, - &mut self.generation_state.state_ptrs.storage, - &inputs.tries, - ) - .expect("Invalid MPT data for preinitialization"); + let trie_root_ptrs = self + .generation_state + .preinitialize_trie_data_and_get_trie_ptrs(tries); let trie_roots_after = &inputs.trie_roots_after; self.generation_state.trie_root_ptrs = trie_root_ptrs; 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 b31c05233..9d7272cef 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs @@ -13,15 +13,10 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::generation::linked_list::testing::LinkedList; -use crate::generation::linked_list::ACCOUNTS_LINKED_LIST_NODE_SIZE; -use crate::generation::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use crate::memory::segments::Segment; use crate::witness::memory::MemoryAddress; use crate::witness::memory::MemorySegmentState; -pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; -pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; - fn init_logger() { let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "debug")); } diff --git a/evm_arithmetization/src/generation/linked_list.rs b/evm_arithmetization/src/generation/linked_list.rs index 5acfa0c14..71a3e058a 100644 --- a/evm_arithmetization/src/generation/linked_list.rs +++ b/evm_arithmetization/src/generation/linked_list.rs @@ -9,6 +9,10 @@ pub const ACCOUNTS_LINKED_LIST_NODE_SIZE: usize = 4; pub const STORAGE_LINKED_LIST_NODE_SIZE: usize = 5; pub const STATE_LINKED_LIST_NODE_SIZE: usize = 4; +pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; +pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; +pub(crate) type StateLinkedList<'a> = LinkedList<'a, STATE_LINKED_LIST_NODE_SIZE>; + pub const DUMMYHEAD: (U256, U256) = (U256::MAX, U256::zero()); // Provides quick access to pointers that reference the memory location From 562ee7f4f76547c4c69f31dac015fe9ae4f74475 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Mon, 21 Oct 2024 15:47:24 +0200 Subject: [PATCH 23/60] Use poseidon empty hash instead of keccak's --- Cargo.lock | 1 + evm_arithmetization/Cargo.toml | 1 + .../src/cpu/kernel/asm/account_code.asm | 12 +++++++++++- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 2 +- .../src/cpu/kernel/asm/core/process_txn.asm | 6 +++++- evm_arithmetization/src/cpu/kernel/asm/main.asm | 10 ++++++---- evm_arithmetization/src/generation/mod.rs | 2 +- evm_arithmetization/src/prover.rs | 1 + smt_trie/Cargo.toml | 1 + smt_trie/src/smt.rs | 9 ++++++++- zero/Cargo.toml | 2 +- 11 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46fbc04f3..06131a9d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4586,6 +4586,7 @@ dependencies = [ "ethereum-types", "hex-literal", "log", + "mpt_trie", "plonky2", "rand", "serde", diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index 12ea9dcba..ab9ac06a2 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -58,6 +58,7 @@ hex = { workspace = true } ripemd = { workspace = true } [features] +default = ["cdk_erigon"] asmtools = ["hex"] polygon_pos = [] cdk_erigon = ["smt_trie"] diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 463d22ec5..8f7f615d5 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -53,10 +53,20 @@ global extcodehash: %%after: %endmacro -%macro ext_code_empty +#[cfg(feature = eth_mainnet)] +{ + %macro ext_code_empty %extcodehash %eq_const(@EMPTY_STRING_HASH) %endmacro +} +#[cfg(feature = cdk_erigon)] +{ + %macro ext_code_empty + %extcodehash + %eq_const(@EMPTY_STRING_POSEIDON_HASH) + %endmacro +} %macro extcodesize %stack (address) -> (address, %%after) diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index ee535f0f4..c5ad2d7d3 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -106,7 +106,7 @@ global create_scalable_l2_account: // the code hash // stack: retdest - PUSH @EMPTY_STRING_HASH + PUSH @EMPTY_STRING_POSEIDON_HASH PUSH @ADDRESS_SCALABLE_L2 global debug_setting_scalable_code: %set_code // code hash diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index f50cef72b..19748f1d6 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -16,6 +16,7 @@ global process_normalized_txn: // Assert gas_limit >= intrinsic_gas. %mload_txn_field(@TXN_FIELD_GAS_LIMIT) +global debug_invalid_txn: %assert_ge(invalid_txn) // Assert block gas limit >= txn gas limit. @@ -32,11 +33,14 @@ global process_normalized_txn: // stack: sender_nonce, sender, retdest %mload_txn_field(@TXN_FIELD_NONCE) // stack: tx_nonce, sender_nonce, sender, retdest +global debug_eq_nonce: %assert_eq(invalid_txn_1) // stack: sender, retdest // Assert sender has no code. - DUP1 %ext_code_empty %assert_nonzero(invalid_txn_1) + DUP1 %ext_code_empty +global debug_no_code: + %assert_nonzero(invalid_txn_1) // stack: sender, retdest // Assert sender balance >= gas_limit * gas_price + value. diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 363ca53ee..75651df3c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -135,9 +135,9 @@ global start_txns: #[cfg(feature = cdk_erigon)] { // If txn_idx == 0, perform pre-state execution for CDK erigon. - %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) - ISZERO - %jumpi(pre_block_execution) + // %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) + // ISZERO + // %jumpi(pre_block_execution) } // stack: init_gas_used, txn_counter, num_nibbles, txn_nb @@ -186,7 +186,9 @@ global txn_loop_after: global perform_final_checks: // stack: cum_gas, txn_counter, num_nibbles, txn_nb // Check that we end up with the correct `cum_gas`, `txn_nb` and bloom filter. - %mload_global_metadata(@GLOBAL_METADATA_BLOCK_GAS_USED_AFTER) %assert_eq + %mload_global_metadata(@GLOBAL_METADATA_BLOCK_GAS_USED_AFTER) +global debug_gas_error: + %assert_eq DUP3 %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_AFTER) %assert_eq %pop3 diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 975f031ee..eb407fc4a 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -693,4 +693,4 @@ pub(crate) fn output_debug_tries(state: &GenerationState) -> an } Ok(()) -} +} \ No newline at end of file diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 079fe3469..0a5aa7b90 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -358,6 +358,7 @@ pub fn check_abort_signal(abort_signal: Option>) -> Result<()> { pub(crate) fn features_check(inputs: &TrimmedGenerationInputs) { if !cfg!(feature = "eth_mainnet") { assert!(inputs.block_metadata.parent_beacon_block_root.is_zero()); + println!("block blob gas used = {:?}", inputs.block_metadata.block_blob_gas_used); assert!(inputs.block_metadata.block_blob_gas_used.is_zero()); assert!(inputs.block_metadata.block_excess_blob_gas.is_zero()); } diff --git a/smt_trie/Cargo.toml b/smt_trie/Cargo.toml index 2907c63e7..9a0e8c009 100644 --- a/smt_trie/Cargo.toml +++ b/smt_trie/Cargo.toml @@ -17,6 +17,7 @@ keywords.workspace = true ethereum-types = { workspace = true } hex-literal = { workspace = true } plonky2 = { workspace = true } +mpt_trie = {workspace = true} rand = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } log = { workspace = true } diff --git a/smt_trie/src/smt.rs b/smt_trie/src/smt.rs index 76b27ca09..32cbcd5ba 100644 --- a/smt_trie/src/smt.rs +++ b/smt_trie/src/smt.rs @@ -5,7 +5,7 @@ use std::borrow::Borrow; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::{Display, Formatter}; -use ethereum_types::U256; +use ethereum_types::{H256, U256}; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::{Field, PrimeField64}; use plonky2::hash::poseidon::{Poseidon, PoseidonHash}; @@ -17,6 +17,7 @@ use crate::db::{Db, MemoryDb}; use crate::utils::{ f2limbs, get_unique_sibling, hash0, hash_key_hash, hashout2u, key2u, limbs2f, u2h, u2k, }; +use mpt_trie::partial_trie::HashedPartialTrie; pub(crate) const HASH_TYPE: u8 = 0; pub(crate) const INTERNAL_TYPE: u8 = 1; @@ -685,3 +686,9 @@ fn _hash_serialize(v: &[U256], ptr: usize) -> HashOut { _ => panic!("Should not happen"), } } + +impl From<(HashedPartialTrie, Vec<(H256, HashedPartialTrie)>)> for Smt { + fn from(_: (HashedPartialTrie, Vec<(H256, HashedPartialTrie)>)) -> Self { + todo!() + } +} diff --git a/zero/Cargo.toml b/zero/Cargo.toml index 7bc42709c..e5cbf63a1 100644 --- a/zero/Cargo.toml +++ b/zero/Cargo.toml @@ -60,7 +60,7 @@ vergen-git2 = { version = "1.0.0", features = ["build"] } [features] -default = ["eth_mainnet"] +default = ["cdk_erigon"] eth_mainnet = ["evm_arithmetization/eth_mainnet", "trace_decoder/eth_mainnet"] cdk_erigon = ["evm_arithmetization/cdk_erigon", "trace_decoder/cdk_erigon"] polygon_pos = ["evm_arithmetization/polygon_pos", "trace_decoder/polygon_pos"] From 3a4f5fcd9e015fa8a9b223b710deadb51eada791 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Mon, 21 Oct 2024 16:46:36 +0200 Subject: [PATCH 24/60] Fix remove key generation input --- evm_arithmetization/src/cpu/kernel/aggregator.rs | 3 ++- .../src/cpu/kernel/asm/journal/storage_change.asm | 4 +--- .../kernel/asm/linked_list/storage_linked_list.asm | 10 ++++++++++ .../asm/linked_list/type2/state_linked_list.asm | 4 ++-- .../cpu/kernel/asm/mpt/storage/storage_write.asm | 5 ++--- evm_arithmetization/src/generation/prover_input.rs | 13 +++++++++---- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index feb592c66..947367d31 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -12,7 +12,7 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 } else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { - 160 + 159 } else { // unreachable 0 @@ -21,6 +21,7 @@ pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ "global jumped_to_0: PANIC", "global jumped_to_1: PANIC", + #[cfg(feature = "eth_mainnet")] include_str!("asm/beacon_roots.asm"), include_str!("asm/bignum/add.asm"), include_str!("asm/bignum/addmul.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm index 3fd20ee19..3ab586e36 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/storage_change.asm @@ -16,8 +16,6 @@ global revert_storage_change: delete: // stack: address, slot, prev_value, retdest - %addr_to_state_key - // stack: addr_key, slot, prev_value, retdest - %remove_slot_from_addr_key + %remove_slot_from_addr POP JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm index 840081382..6d69ac0e4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/storage_linked_list.asm @@ -426,6 +426,16 @@ global remove_slot: %%after: %endmacro +%macro remove_slot_from_addr + // stack: addr, slot + %addr_to_state_key + SWAP1 + %slot_to_storage_key + %stack (key, addr_key) -> (addr_key, key, %%after) + %jump(remove_slot) +%%after: +%endmacro + %macro read_slot_from_current_addr // stack: slot %slot_to_storage_key diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index 1dd8b6688..01b888df7 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -374,7 +374,7 @@ global debug_o_margot: %remove_key %endmacro -%macro remove_slot_from_addr_key +%macro remove_slot_from_addr %key_storage %remove_key %endmacro @@ -383,7 +383,7 @@ global debug_o_margot: /// Panics if the key is not in the list. global remove_key: // stack: key, retdest - PROVER_INPUT(linked_list::remove_slot) + PROVER_INPUT(linked_list::remove_state) // stack: pred_ptr/4, key, retdest %get_valid_state_ptr // stack: pred_ptr, key, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm index 17513c7cd..91bb61e2a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -135,9 +135,8 @@ sstore_noop: sstore_delete: // stack: slot, value, kexit_info %address - %addr_to_state_key - // stack: addr_key, slot, value, kexit_info - %remove_slot_from_addr_key + // stack: addr, slot, value, kexit_info + %remove_slot_from_addr // stack: value, kexit_info POP EXIT_KERNEL diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 8633e86ce..bafee07ae 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -417,7 +417,7 @@ impl GenerationState { StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) ); log::debug!("state btree = {:#?}", self.state_pointers); - log::debug!("input state = {}", self.inputs.trimmed_tries.state_trie); + log::debug!("input state popopo = {}", self.inputs.trimmed_tries.state_trie); match input_fn.0[1].as_str() { "insert_state" | "search_state" => self.run_next_insert_state(input_fn), @@ -643,8 +643,8 @@ impl GenerationState { } /// Returns a pointer `ptr` to a node of the form [..] -> [next_addr, ..] - /// list such that `next_addr = addr` and `addr` is the top of the stack. - /// If the element is not in the list, loops forever. + /// such that `next_addr = addr` and `addr` is the top of the stack. + /// If the element is not in the list, returns an error. #[cfg(feature = "eth_mainnet")] fn run_next_remove_account(&mut self) -> Result { let addr = stack_peek(self, 0)?; @@ -662,12 +662,17 @@ impl GenerationState { } /// Returns a pointer `ptr` to a node of the form [..] -> [next_key, ..] - /// list such that `next_key = addr` and `key` is the top of the stack. + /// such that `next_key = addr` and `key` is the top of the stack. /// If the element is not in the list, returns an error. #[cfg(feature = "cdk_erigon")] fn run_next_remove_state(&mut self) -> Result { let addr = stack_peek(self, 0)?; + log::debug!( + "los que viene antes: = {:?}", + self.state_pointers.range(..addr).next_back() + ); + let (_, &ptr) = self .state_pointers .range(..addr) From 7605d49d81119739c19cee0c651d7a7a1b6a9d0c Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 22 Oct 2024 12:03:44 +0200 Subject: [PATCH 25/60] Fix errors on deletions --- evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm | 2 +- .../src/cpu/kernel/asm/linked_list/type2/final_tries.asm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm index 61a02fa10..39b8be23b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm @@ -17,7 +17,7 @@ global nonce: #[cfg(feature = cdk_erigon)] { // stack: address, retdest - %read_nonce %mload_trie_data + %read_nonce // stack: nonce, retdest SWAP1 JUMP } diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm index 5a9b50ab4..4a7951470 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm @@ -69,8 +69,8 @@ global debug_delete_node: // stack: node_ptr_ptr, root_ptr, retdest DUP1 MLOAD_GENERAL - %stack (key, node_ptr_ptr, root_ptr) -> (root_ptr, 64, key, after_mpt_delete, node_ptr_ptr) - %jump(mpt_delete) + %stack (key, node_ptr_ptr, root_ptr) -> (root_ptr, key, after_mpt_delete, node_ptr_ptr) + %jump(smt_delete) after_mpt_delete: // stack: root_ptr', node_ptr_ptr, retdest SWAP1 From 8a32380f886f90c8056f244d8f0553091defef44 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 22 Oct 2024 15:09:23 +0200 Subject: [PATCH 26/60] Add fix from PR #661 --- .../src/cpu/kernel/asm/memory/metadata.asm | 11 +++++------ .../src/cpu/kernel/asm/memory/syscalls.asm | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/memory/metadata.asm b/evm_arithmetization/src/cpu/kernel/asm/memory/metadata.asm index 5e94794f6..5ac85f1b3 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/memory/metadata.asm @@ -457,17 +457,16 @@ zero_hash: // stack: sum %endmacro -// Adds the two top elements of the stack, and faults in case of overflow modulo 2^32. -%macro add_u32_or_fault +// Checks that the addition of the two top elements of the stack does not overflow modulo 2^32. +%macro check_u32_add // stack: x, y %add_or_fault - DUP1 - // stack: sum, sum + // stack: sum PUSH 0xffffffff // 2^32 - 1 LT - // stack: is_overflow, sum + // stack: is_overflow %jumpi(fault_exception) - // stack: sum + // stack: (empty) %endmacro %macro call_depth diff --git a/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm b/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm index c0f4f1e4a..ee1de1197 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm @@ -79,13 +79,7 @@ calldataload_large_offset: // stack: kexit_info, dest_offset, offset, size %wcopy_charge_gas - // Ensure that `offset + size` won't overflow the reserved 32-bit limb - // of the `virtual` component of the source memory address. - DUP4 DUP4 - // stack: offset, size, kexit_info, dest_offset, offset, size - %add_u32_or_fault - - %stack (offset_plus_size, kexit_info, dest_offset, offset, size) -> + %stack (kexit_info, dest_offset, offset, size) -> (dest_offset, size, kexit_info, dest_offset, offset, size) %add_or_fault // stack: expanded_num_bytes, kexit_info, dest_offset, offset, size, kexit_info @@ -98,10 +92,18 @@ calldataload_large_offset: // stack: offset, total_size, kexit_info, dest_offset, offset, size GT %jumpi(wcopy_large_offset) + // stack: kexit_info, dest_offset, offset, size + // Ensure that `offset + size` won't overflow the reserved 32-bit limb + // of the `virtual` component of the source memory address. + DUP4 DUP4 + // stack: offset, size, kexit_info, dest_offset, offset, size + %check_u32_add + // stack: kexit_info, dest_offset, offset, size GET_CONTEXT PUSH $segment - // stack: segment, context, kexit_info, dest_offset, offset, size + %build_address_no_offset + // stack: base_addr, kexit_info, dest_offset, offset, size %jump(wcopy_within_bounds) %endmacro From 6306f397489f0444f5861f0d97862eb491b43e8b Mon Sep 17 00:00:00 2001 From: hratoanina Date: Tue, 22 Oct 2024 12:46:29 -0400 Subject: [PATCH 27/60] Merge contd --- .../src/cpu/kernel/interpreter.rs | 6 +-- evm_arithmetization/src/cpu/kernel/mod.rs | 2 +- .../src/cpu/kernel/tests/mod.rs | 2 +- .../src/cpu/kernel/tests/mpt/linked_list.rs | 7 ++++ .../src/cpu/kernel/tests/mpt/mod.rs | 7 +++- .../src/generation/linked_list.rs | 32 ++++++++++++--- .../src/generation/prover_input.rs | 35 +++++++++------- evm_arithmetization/src/generation/state.rs | 38 ++++++++++-------- evm_arithmetization/src/witness/transition.rs | 40 ++++++++++--------- 9 files changed, 109 insertions(+), 60 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 088750665..84063ccb4 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -21,7 +21,7 @@ use crate::cpu::columns::CpuColumnsView; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::generation::debug_inputs; -use crate::generation::linked_list::LinkedListsPtrs; +use crate::generation::linked_list::{AccessLinkedListsPtrs, StateLinkedListsPtrs}; use crate::generation::mpt::TrieRootPtrs; use crate::generation::rlp::all_rlp_prover_inputs_reversed; use crate::generation::state::{ @@ -117,8 +117,8 @@ pub(crate) struct ExtraSegmentData { pub(crate) ger_prover_inputs: Vec, pub(crate) trie_root_ptrs: TrieRootPtrs, pub(crate) jumpdest_table: Option>>, - pub(crate) access_lists_ptrs: LinkedListsPtrs, - pub(crate) state_ptrs: LinkedListsPtrs, + pub(crate) access_lists_ptrs: AccessLinkedListsPtrs, + pub(crate) state_ptrs: StateLinkedListsPtrs, pub(crate) next_txn_index: usize, } diff --git a/evm_arithmetization/src/cpu/kernel/mod.rs b/evm_arithmetization/src/cpu/kernel/mod.rs index 8a2f4317b..50e377ae8 100644 --- a/evm_arithmetization/src/cpu/kernel/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/mod.rs @@ -18,7 +18,7 @@ pub use constants::cancun_constants; pub use constants::global_exit_root; #[cfg(test)] -mod tests; +pub(crate) mod tests; use assembler::assemble; use parser::parse; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mod.rs index 2b983d099..4fce68600 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mod.rs @@ -18,7 +18,7 @@ mod init_exc_stop; mod kernel_consistency; mod log; mod mcopy; -mod mpt; +pub(crate) mod mpt; mod packing; mod receipt; mod rlp; 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 9d7272cef..979a15170 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs @@ -13,10 +13,17 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::generation::linked_list::testing::LinkedList; +use crate::generation::linked_list::ACCOUNTS_LINKED_LIST_NODE_SIZE; +use crate::generation::linked_list::STATE_LINKED_LIST_NODE_SIZE; +use crate::generation::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use crate::memory::segments::Segment; use crate::witness::memory::MemoryAddress; use crate::witness::memory::MemorySegmentState; +pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; +pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; +pub(crate) type StateLinkedList<'a> = LinkedList<'a, STATE_LINKED_LIST_NODE_SIZE>; + fn init_logger() { let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "debug")); } diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 17ff18a9b..5ebc0f4a5 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -6,12 +6,17 @@ use mpt_trie::partial_trie::PartialTrie; use crate::generation::mpt::AccountRlp; use crate::Node; +#[cfg(feature = "eth_mainnet")] mod delete; +#[cfg(feature = "eth_mainnet")] mod hash; mod hex_prefix; +#[cfg(feature = "eth_mainnet")] mod insert; -mod linked_list; +pub(crate) mod linked_list; +#[cfg(feature = "eth_mainnet")] mod load; +#[cfg(feature = "eth_mainnet")] mod read; pub(crate) fn nibbles_64>(v: T) -> Nibbles { diff --git a/evm_arithmetization/src/generation/linked_list.rs b/evm_arithmetization/src/generation/linked_list.rs index 71a3e058a..a8a9febb0 100644 --- a/evm_arithmetization/src/generation/linked_list.rs +++ b/evm_arithmetization/src/generation/linked_list.rs @@ -9,16 +9,27 @@ pub const ACCOUNTS_LINKED_LIST_NODE_SIZE: usize = 4; pub const STORAGE_LINKED_LIST_NODE_SIZE: usize = 5; pub const STATE_LINKED_LIST_NODE_SIZE: usize = 4; -pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; -pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; -pub(crate) type StateLinkedList<'a> = LinkedList<'a, STATE_LINKED_LIST_NODE_SIZE>; - pub const DUMMYHEAD: (U256, U256) = (U256::MAX, U256::zero()); // Provides quick access to pointers that reference the memory location // of a storage or accounts linked list node, containing a specific key. #[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub(crate) struct LinkedListsPtrs { +pub(crate) struct AccessLinkedListsPtrs { + /// Each entry contains the pair (key, ptr) where key is the (hashed) key + /// of an account in the accounts linked list, and ptr is the respective + /// node address in memory. + pub(crate) accounts: BTreeMap, + /// Each entry contains the pair ((account_key, slot_key), ptr) where + /// account_key is the (hashed) key of an account, slot_key is the slot + /// key, and ptr is the respective node address in memory. + pub(crate) storage: BTreeMap<(U256, U256), usize>, +} + +// Provides quick access to pointers that reference the memory location +// of state nodes. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[cfg(feature = "eth_mainnet")] +pub(crate) struct StateLinkedListsPtrs { /// Each entry contains the pair (key, ptr) where key is the (hashed) key /// of an account in the accounts linked list, and ptr is the respective /// node address in memory. @@ -29,6 +40,17 @@ pub(crate) struct LinkedListsPtrs { pub(crate) storage: BTreeMap<(U256, U256), usize>, } +// Provides quick access to pointers that reference the memory location +// of state nodes. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[cfg(feature = "cdk_erigon")] +pub(crate) struct StateLinkedListsPtrs { + /// Each entry contains the pair (key, ptr) where key is the (hashed) key + /// of an account in the accounts linked list, and ptr is the respective + /// node address in memory. + pub(crate) state: BTreeMap, +} + pub(crate) fn empty_list_mem(offset: usize) -> [Option; N] { std::array::from_fn(|i| { if i == 0 { diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 7b245242c..91dacf41e 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; #[cfg(test)] use super::linked_list::testing::{LinkedList, ADDRESSES_ACCESS_LIST_LEN}; use super::linked_list::{ - LinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD, STORAGE_LINKED_LIST_NODE_SIZE, + AccessLinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD, STORAGE_LINKED_LIST_NODE_SIZE, }; #[cfg(feature = "eth_mainnet")] use super::mpt::load_state_mpt; @@ -410,14 +410,21 @@ impl GenerationState { /// jump address. #[cfg(feature = "cdk_erigon")] fn run_linked_list(&mut self, input_fn: &ProverInputFn) -> Result { - use crate::generation::linked_list::StateLinkedList; let mem = self.memory.get_preinit_memory(Segment::AccountsLinkedList); - log::debug!( - "state ll = {:?}", - StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) - ); - log::debug!("state btree = {:#?}", self.state_pointers); - log::debug!("input state popopo = {}", self.inputs.trimmed_tries.state_trie); + + #[cfg(test)] + { + use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; + log::debug!( + "state ll = {:?}", + StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + ); + log::debug!("state btree = {:#?}", self.state_ptrs); + log::debug!( + "input state popopo = {}", + self.inputs.trimmed_tries.state_trie + ); + } match input_fn.0[1].as_str() { "insert_state" | "search_state" => self.run_next_insert_state(input_fn), @@ -579,7 +586,7 @@ impl GenerationState { } fn run_reset(&mut self) -> Result { - self.access_lists_ptrs = LinkedListsPtrs::default(); + self.access_lists_ptrs = AccessLinkedListsPtrs::default(); Ok(U256::zero()) } @@ -613,13 +620,13 @@ impl GenerationState { fn run_next_insert_state(&mut self, input_fn: &ProverInputFn) -> Result { let key = stack_peek(self, 0)?; let (&pred_key, &pred_ptr) = self - .state_pointers + .state_ptrs .range(..=key) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); if pred_key != key && input_fn.0[1].as_str() == "insert_state" { - self.state_pointers.insert( + self.state_ptrs.insert( key, u256_to_usize( self.memory @@ -689,15 +696,15 @@ impl GenerationState { log::debug!( "los que viene antes: = {:?}", - self.state_pointers.range(..addr).next_back() + self.state_ptrs.range(..addr).next_back() ); let (_, &ptr) = self - .state_pointers + .state_ptrs .range(..addr) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); - self.state_pointers + self.state_ptrs .remove(&addr) .ok_or(ProgramError::ProverInputError(InvalidInput))?; diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index afefbd4b2..0506e0051 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -10,7 +10,6 @@ use plonky2::hash::hash_types::RichField; #[cfg(feature = "cdk_erigon")] use smt_trie::code::hash_bytecode_u256; -use super::linked_list::LinkedListsPtrs; use super::mpt::TrieRootPtrs; use super::segments::GenerationSegmentData; use super::{TrieInputs, TrimmedGenerationInputs, NUM_EXTRA_CYCLES_AFTER}; @@ -19,7 +18,7 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::stack::MAX_USER_STACK_SIZE; use crate::generation::linked_list::{ - empty_list_mem, StateLinkedList, STATE_LINKED_LIST_NODE_SIZE, + empty_list_mem, AccessLinkedListsPtrs, StateLinkedListsPtrs, STATE_LINKED_LIST_NODE_SIZE, }; #[cfg(feature = "eth_mainnet")] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; @@ -206,10 +205,14 @@ pub(crate) trait State { .get_generation_state() .memory .get_preinit_memory(Segment::AccountsLinkedList); - log::debug!( - "initial state linked list = {:?}", - StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) - ); + #[cfg(test)] + { + use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; + log::debug!( + "initial state linked list = {:?}", + StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + ); + } loop { let registers = self.get_registers(); @@ -397,11 +400,11 @@ pub struct GenerationState { /// Provides quick access to pointers that reference the location /// of either and account or a slot in the respective access list. - pub(crate) access_lists_ptrs: LinkedListsPtrs, + pub(crate) access_lists_ptrs: AccessLinkedListsPtrs, /// Provides quick access to pointers that reference the memory location of /// either and account or a slot in the respective access list. - pub(crate) state_ptrs: LinkedListsPtrs, + pub(crate) state_ptrs: StateLinkedListsPtrs, } impl GenerationState { @@ -466,7 +469,7 @@ impl GenerationState { .state_trie .load_linked_list_data::<{ Segment::AccountsLinkedList as usize }>( &mut state_linked_list_data, - &mut self.state_pointers, + &mut self.state_ptrs.accounts, ); self.memory.insert_preinitialized_segment( @@ -510,8 +513,8 @@ impl GenerationState { receipt_root_ptr: 0, }, jumpdest_table: None, - access_lists_ptrs: LinkedListsPtrs::default(), - state_ptrs: LinkedListsPtrs::default(), + access_lists_ptrs: AccessLinkedListsPtrs::default(), + state_ptrs: StateLinkedListsPtrs::default(), ger_prover_inputs, }; let trie_root_ptrs = state.preinitialize_trie_data_and_get_trie_ptrs(&inputs.tries); @@ -538,8 +541,8 @@ impl GenerationState { receipt_root_ptr: 0, }, jumpdest_table: None, - access_lists_ptrs: LinkedListsPtrs::default(), - state_ptrs: LinkedListsPtrs::default(), + access_lists_ptrs: AccessLinkedListsPtrs::default(), + state_ptrs: StateLinkedListsPtrs::default(), ger_prover_inputs, }; let trie_root_ptrs = state.preinitialize_trie_data_and_get_trie_ptrs(&inputs.tries); @@ -710,7 +713,8 @@ impl GenerationState { receipt_root_ptr: 0, }, jumpdest_table: None, - state_pointers: self.state_pointers.clone(), + access_lists_ptrs: self.access_lists_ptrs.clone(), + state_ptrs: self.state_ptrs.clone(), } } @@ -756,8 +760,10 @@ impl GenerationState { .clone_from(&segment_data.extra_data.trie_root_ptrs); self.jumpdest_table .clone_from(&segment_data.extra_data.jumpdest_table); - self.state_pointers - .clone_from(&segment_data.extra_data.state); + self.access_lists_ptrs + .clone_from(&segment_data.extra_data.access_lists_ptrs); + self.state_ptrs + .clone_from(&segment_data.extra_data.state_ptrs); self.next_txn_index = segment_data.extra_data.next_txn_index; self.registers = RegistersState { program_counter: self.registers.program_counter, diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 610356a77..6d6162252 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -8,12 +8,12 @@ use crate::cpu::columns::CpuColumnsView; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; +use crate::cpu::kernel::constants::MAX_CODE_SIZE; use crate::cpu::kernel::opcodes::get_opcode; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::stack::{ EQ_STACK_BEHAVIOR, IS_ZERO_STACK_BEHAVIOR, JUMPI_OP, JUMP_OP, MIGHT_OVERFLOW, STACK_BEHAVIORS, }; -use crate::generation::linked_list::StateLinkedList; use crate::generation::state::State; use crate::memory::segments::Segment; // TO REMOVE! @@ -312,26 +312,28 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o state.get_generation_state().stack(), ), ); - if KERNEL.offset_name(pc) == "insert_all_initial_nodes" { - let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::AccountsLinkedList); - log::debug!( - "state linked list = {:?}", - StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) - ); - } + // if KERNEL.offset_name(pc) == "insert_all_initial_nodes" { + // let mem = state + // .get_generation_state() + // .memory + // .get_preinit_memory(Segment::AccountsLinkedList); + // log::debug!( + // "state linked list = {:?}", + // StateLinkedList::from_mem_and_segment(&mem, + // Segment::AccountsLinkedList) ); + // } if KERNEL.offset_name(pc) == "smt_hash_state" { - let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::AccountsLinkedList); - log::debug!( - "state linked list = {:?}", - StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) - ); + // let mem = state + // .get_generation_state() + // .memory + // .get_preinit_memory(Segment::AccountsLinkedList); + + // log::debug!( + // "state linked list = {:?}", + // StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + // ); + let root_ptr = u256_to_usize( state .get_generation_state() From 530f86c0ff3c646632b141c3bd8a8a08131b73f4 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 23 Oct 2024 12:44:00 +0200 Subject: [PATCH 28/60] Fix randomStatetest368 --- .../src/cpu/kernel/asm/account_code.asm | 64 +++++++++++++++++++ .../src/cpu/kernel/asm/core/create.asm | 32 ++++++++-- .../core/create_type2_contract_account.asm | 17 +++-- 3 files changed, 99 insertions(+), 14 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 8f7f615d5..f33d444c8 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -191,4 +191,68 @@ load_code_padded_ctd: remove_padding_after: %stack (offset, ctx, retdest) -> (retdest, offset) JUMP + + // Convenience macro to call poseidon_hash_code_unpadded and return where we left off. + %macro poseidon_hash_code_unpadded + %stack (addr, len) -> (addr, len, %%after) + %jump(poseidon_hash_code_unpadded) + %%after: + %endmacro + + /// Applies the padding rule to the code located at the provided address before hashing it. + /// Memory cells after the last code byte will be overwritten. + global poseidon_hash_code_unpadded: + // stack: addr, len, retdest + DUP2 ISZERO %jumpi(poseidon_empty_code) + DUP2 DUP2 ADD + // stack: padding_addr, addr, len, retdest + + // write 1 after the last code byte + DUP1 PUSH 1 MSTORE_GENERAL + // stack: padding_addr, addr, len, retdest + %increment + // stack: padding_addr, addr, len, retdest + + // Pad with 0s until the length is a multiple of 56 + PUSH 56 + DUP4 %increment + // stack: curr_len, 56, padding_addr, addr, len, retdest + PUSH 56 SUB + // stack: 56 - curr_len, 56, padding_addr, addr, len, retdest + MOD + // stack: padding_len, padding_addr, addr, len, retdest + SWAP3 DUP4 + // stack: padding_len, len, padding_addr, addr, padding_len, retdest + ADD + // stack: last_byte_offset, padding_addr, addr, padding_len, retdest + %stack (last_byte_offset, padding_addr, addr, padding_len) + -> (padding_addr, padding_len, after_padding, addr, last_byte_offset) + %jump(memset) + after_padding: + // stack: addr, last_byte_offset, retdest + + // Xor the last element with 0x80 + PUSH 1 DUP3 ADD + // stack: total_code_len, addr, last_byte_offset, retdest + SWAP2 + // stack: last_byte_offset, addr, total_code_len, retdest + DUP2 ADD + // stack: last_byte_addr, addr, total_code_len, retdest + DUP1 MLOAD_GENERAL + // stack: last_byte, last_byte_addr, addr, total_code_len, retdest + PUSH 0x80 ADD + // stack: last_byte_updated, last_byte_addr, addr, total_code_len, retdest + MSTORE_GENERAL + // stack: addr, total_code_len, retdest + + POSEIDON_GENERAL + // stack: codehash, retdest + SWAP1 + JUMP + + global poseidon_empty_code: + // stack: addr, len, retdest + %stack (addr, len, retdest) -> (retdest, @EMPTY_STRING_POSEIDON_HASH) + JUMP + } diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index b9aaee758..54e330811 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -92,6 +92,7 @@ global create_common: %create_context // stack: new_ctx, address, value, code_offset, code_len, kexit_info +global debug_new_ctx: GET_CONTEXT // stack: src_ctx, new_ctx, address, value, code_offset, code_len, kexit_info @@ -113,13 +114,16 @@ global create_common: run_constructor: // stack: new_ctx, value, address, kexit_info +global debug_run_constructor: SWAP1 %set_new_ctx_value +global debug_1: // stack: new_ctx, address, kexit_info // Each line in the block below does not change the stack. DUP2 %set_new_ctx_addr %address %set_new_ctx_caller %set_new_ctx_parent_pc(after_constructor) +global debug_2: // stack: new_ctx, address, kexit_info // All but 1/64 of the sender's remaining gas goes to the constructor. @@ -128,11 +132,14 @@ run_constructor: %drain_all_but_one_64th_gas %stack (kexit_info, drained_gas, address, new_ctx) -> (drained_gas, new_ctx, address, kexit_info) %set_new_ctx_gas_limit +global debug_3: // stack: new_ctx, address, kexit_info // Create the new contract account in the state trie. DUP2 +global debug_before_create_contract_account: %create_contract_account +global debug_after_create_contract_account: // stack: status, new_ctx, address, kexit_info %jumpi(create_collision) @@ -172,7 +179,15 @@ after_constructor: %returndatasize PUSH @SEGMENT_RETURNDATA GET_CONTEXT %build_address_no_offset // stack: addr, len - KECCAK_GENERAL + #[cfg(feature = eth_mainnet)] + { + KECCAK_GENERAL + } + #[cfg(feature = cdk_erigon)] + { + %poseidon_hash_code_unpadded + global debug_poseidon_output: + } // stack: codehash, leftover_gas, success, address, kexit_info %observe_new_contract DUP4 @@ -276,13 +291,20 @@ global set_codehash: DUP2 global debug_reading_code_length: %read_code_length - %stack (prev_code_length, prev_codehash, addr) -> (addr, prev_codehash, prev_code_length, addr) + %stack (prev_code_length, prev_codehash, addr) -> (addr, prev_codehash, prev_code_length, prev_code_length, addr) %journal_add_code_change // Add the code change to the journal. - // stack: addr, codehash, retdest - DUP2 DUP2 + // stack: prev_code_length, addr, codehash, retdest + DUP3 DUP3 global debug_setting_code: %set_code - %returndatasize DUP2 + // stack: prev_code_length, addr, codehash, retdest + %returndatasize + SWAP1 DUP2 SUB + // stack: code_length - prev_code_length, code_length, addr, code_hash, retdest + %jumpi(code_length_changed) + %pop3 JUMP + code_length_changed: + DUP2 global debug_setting_code_lenght: %set_code_length // stack: addr, codehash, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm index adbecd39b..e4e244cb9 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm @@ -5,8 +5,7 @@ // stack: address DUP1 %insert_touched_addresses DUP1 %append_created_contracts - POP - %read_code ISZERO %jumpi(%%add_account) + DUP1 %read_code ISZERO %jumpi(%%add_account) // Check that the nonce is 0. // stack: address DUP1 %nonce @@ -41,13 +40,13 @@ PUSH 0 // success %jump(%%end) -// If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. -// (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) -// So we return 1 to indicate an error. -%%error_collision: - %stack (address) -> (1) -%%end: - // stack: status + // If the nonce is nonzero or the code is non-empty, that means a contract has already been deployed to this address. + // (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) + // So we return 1 to indicate an error. + %%error_collision: + %stack (address) -> (1) + %%end: + // stack: status %endmacro %macro append_created_contracts From 5a637f7c7d7e3052cd8a7db4598b73b0e72dda01 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 23 Oct 2024 13:34:15 +0200 Subject: [PATCH 29/60] Turn insert_key with value 0 delete into remove_key --- .../cpu/kernel/asm/linked_list/type2/state_linked_list.asm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index 01b888df7..cd17a72fa 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -179,6 +179,7 @@ store_initial_state_end: /// or modifies the vealue if it was already present. global insert_key: // stack: key, value, retdest + DUP2 ISZERO %jumpi(insert_zero) PROVER_INPUT(linked_list::insert_state) // stack: pred_ptr/4, key, value, retdest %get_valid_state_ptr @@ -209,6 +210,12 @@ global insert_key: // The key is not in the list. PANIC +insert_zero: + // stack: key, value, retdest + %remove_key + POP + JUMP + key_found_with_overwrite: // The key was already in the list // stack: pred_ptr, key, value, retdest From 1777969aa28e15ea8067191939e0c1b42bb601e1 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Fri, 25 Oct 2024 15:22:42 +0200 Subject: [PATCH 30/60] Fix code padding --- .../src/cpu/kernel/asm/account_code.asm | 6 +- .../src/cpu/kernel/asm/balance.asm | 2 +- .../src/cpu/kernel/asm/core/process_txn.asm | 4 +- .../linked_list/type2/state_linked_list.asm | 41 ++++++++--- .../src/cpu/kernel/asm/memory/syscalls.asm | 69 ++++++++++--------- .../cpu/kernel/asm/transactions/type_0.asm | 1 + .../src/generation/prover_input.rs | 3 +- evm_arithmetization/src/witness/transition.rs | 2 +- smt_trie/src/code.rs | 3 + 9 files changed, 81 insertions(+), 50 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index f33d444c8..5e3b5ce77 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -216,10 +216,12 @@ load_code_padded_ctd: // Pad with 0s until the length is a multiple of 56 PUSH 56 DUP4 %increment + global debug_len_p_one: // stack: curr_len, 56, padding_addr, addr, len, retdest - PUSH 56 SUB - // stack: 56 - curr_len, 56, padding_addr, addr, len, retdest + PUSH 56 SWAP1 SUB + // stack: curr_len - 56, 56, padding_addr, addr, len, retdest MOD + global debug_to_padd: // stack: padding_len, padding_addr, addr, len, retdest SWAP3 DUP4 // stack: padding_len, len, padding_addr, addr, padding_len, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/balance.asm b/evm_arithmetization/src/cpu/kernel/asm/balance.asm index 3e4e1711d..11e1bb441 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/balance.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/balance.asm @@ -43,7 +43,7 @@ global balance: // stack: address, retdest %read_balance // stack: balance, retdest - SWAP1 JUMP + SWAP1 JUMP } retzero: %stack (account_ptr, retdest) -> (retdest, 0) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 19748f1d6..7d6fc1ed1 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -213,8 +213,8 @@ global process_contract_creation_txn_after_constructor: PUSH @SEGMENT_RETURNDATA GET_CONTEXT %build_address_no_offset - // stack: addr, len - KECCAK_GENERAL + // stack: addr, len, leftover_gas, new_ctx, address, retdest, success + %poseidon_hash_code_unpadded // stack: codehash, leftover_gas, new_ctx, address, retdest, success %observe_new_contract DUP4 diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index cd17a72fa..f9e78c980 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -387,35 +387,54 @@ global debug_o_margot: %endmacro /// Removes the key and its value from the state linked list. -/// Panics if the key is not in the list. global remove_key: // stack: key, retdest PROVER_INPUT(linked_list::remove_state) // stack: pred_ptr/4, key, retdest %get_valid_state_ptr // stack: pred_ptr, key, retdest + DUP1 %add_const(@STATE_NEXT_NODE_PTR) - // stack: next_ptr_ptr, key, retdest + // stack: next_ptr_ptr, pred_ptr, key, retdest DUP1 MLOAD_GENERAL - // stack: next_ptr, next_ptr_ptr, key, retdest + // stack: next_ptr, next_ptr_ptr, pred_ptr, key, retdest DUP1 MLOAD_GENERAL - // stack: next_key, next_ptr, next_ptr_ptr, key, retdest - DUP4 - %assert_eq - // stack: next_ptr, next_ptr_ptr, key, retdest + // stack: next_key, next_ptr, next_ptr_ptr, pred_ptr, key, retdest + DUP5 + DUP2 + %assert_eq(not_found) + POP + // stack: next_ptr, next_ptr_ptr, pred_ptr, key, retdest %add_const(@STATE_NEXT_NODE_PTR) - // stack: next_next_ptr_ptr, next_ptr_ptr, key, retdest + // stack: next_next_ptr_ptr, next_ptr_ptr, pred_ptr, key, retdest DUP1 MLOAD_GENERAL - // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, key, retdest + // stack: next_next_ptr, next_next_ptr_ptr, next_ptr_ptr, pred_ptr, key, retdest SWAP1 %mstore_u256_max - // stack: next_next_ptr, next_ptr_ptr, key, retdest + // stack: next_next_ptr, next_ptr_ptr, pred_ptr, key, retdest MSTORE_GENERAL - POP + %pop2 JUMP +not_found: + // stack: next_key, next_ptr, next_ptr_ptr, pred_ptr, key, retdest + DUP5 + %assert_lt + // stack: next_ptr, next_ptr_ptr, pred_ptr, key, retdest + %pop2 + MLOAD_GENERAL + // stack: prev_key, key, retdest + SWAP1 + DUP2 + LT + // prev_key < key, prev_key, retdest + SWAP1 + %eq_const(@U256_MAX) + ADD + %assert_nonzero + JUMP %macro read_slot_from_current_addr // stack: slot diff --git a/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm b/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm index ee1de1197..0a3af5c2a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm @@ -119,6 +119,7 @@ calldataload_large_offset: codecopy_within_bounds: +global debug_codecopy_withing_bounds: // stack: total_size, segment, src_ctx, kexit_info, dest_offset, offset, size POP // stack: segment, src_ctx, kexit_info, dest_offset, offset, size @@ -131,17 +132,18 @@ codecopy_within_bounds: %jump(memcpy_bytes) wcopy_within_bounds: - // TODO: rework address creation to have less stack manipulation overhead - // stack: segment, src_ctx, kexit_info, dest_offset, offset, size +global debug_wcopy_within_bounds: + // stack: base_addr, kexit_info, dest_offset, offset, size GET_CONTEXT - %stack (context, segment, src_ctx, kexit_info, dest_offset, offset, size) -> - (src_ctx, segment, offset, @SEGMENT_MAIN_MEMORY, dest_offset, context, size, wcopy_after, kexit_info) - %build_address + %stack (context, base_addr, kexit_info, dest_offset, offset, size) -> + (base_addr, offset, @SEGMENT_MAIN_MEMORY, dest_offset, context, size, wcopy_after, kexit_info) + ADD // SRC SWAP3 %build_address // stack: DST, SRC, size, wcopy_after, kexit_info %jump(memcpy_bytes) wcopy_empty: +global debug_wcopy_empty: // stack: Gverylow, kexit_info, dest_offset, offset, size %charge_gas %stack (kexit_info, dest_offset, offset, size) -> (kexit_info) @@ -149,6 +151,7 @@ wcopy_empty: codecopy_large_offset: +global codecopy_large_offset: // stack: total_size, src_ctx, kexit_info, dest_offset, offset, size POP // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. @@ -160,6 +163,7 @@ codecopy_large_offset: %jump(memset) wcopy_large_offset: +global wcopy_large_offset: // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. // stack: kexit_info, dest_offset, offset, size GET_CONTEXT @@ -169,6 +173,7 @@ wcopy_large_offset: %jump(memset) codecopy_after: +global codecopy_after: // stack: src_ctx, kexit_info DUP1 GET_CONTEXT // stack: ctx, src_ctx, src_ctx, kexit_info @@ -182,11 +187,13 @@ codecopy_after: EXIT_KERNEL codecopy_no_prune: +global codecopy_no_prune: // stack: src_ctx, kexit_info POP EXIT_KERNEL wcopy_after: +global wcopy_after: // stack: kexit_info EXIT_KERNEL @@ -288,24 +295,26 @@ global sys_mcopy: // stack: kexit_info, dest_offset, offset, size GET_CONTEXT PUSH @SEGMENT_MAIN_MEMORY + %build_address_no_offset DUP5 DUP5 LT // stack: dest_offset < offset, kexit_info, dest_offset, offset, size %jumpi(wcopy_within_bounds) - // stack: segment, context, kexit_info, dest_offset, offset, size - DUP6 PUSH 32 %min - // stack: shift=min(size, 32), segment, context, kexit_info, dest_offset, offset, size - DUP6 DUP8 ADD - // stack: offset + size, shift, segment, context, kexit_info, dest_offset, offset, size - DUP6 LT - // stack: dest_offset < offset + size, shift, segment, context, kexit_info, dest_offset, offset, size + // stack: base_addr, kexit_info, dest_offset, offset, size + + DUP5 PUSH 32 %min + // stack: shift=min(size, 32), base_addr, kexit_info, dest_offset, offset, size + DUP5 DUP7 ADD + // stack: offset + size, shift, base_addr, kexit_info, dest_offset, offset, size + DUP5 LT + // stack: dest_offset < offset + size, shift, base_addr, kexit_info, dest_offset, offset, size DUP2 - // stack: shift, dest_offset < offset + size, shift, segment, context, kexit_info, dest_offset, offset, size - DUP9 GT - // stack: size > shift, dest_offset < offset + size, shift, segment, context, kexit_info, dest_offset, offset, size + // stack: shift, dest_offset < offset + size, shift, base_addr, kexit_info, dest_offset, offset, size + DUP8 GT + // stack: size > shift, dest_offset < offset + size, shift, base_addr, kexit_info, dest_offset, offset, size MUL // AND - // stack: (size > shift) && (dest_offset < offset + size), shift, segment, context, kexit_info, dest_offset, offset, size + // stack: (size > shift) && (dest_offset < offset + size), shift, base_addr, kexit_info, dest_offset, offset, size // If the conditions `size > shift` and `dest_offset < offset + size` are satisfied, that means // we will get an overlap that will overwrite some SRC data. In that case, we will proceed to the @@ -314,7 +323,7 @@ global sys_mcopy: // Otherwise, we either have `SRC` < `DST`, or a small enough `size` that a single loop of // `memcpy_bytes` suffices and does not risk to overwrite `SRC` data before being read. - // stack: shift, segment, context, kexit_info, dest_offset, offset, size + // stack: shift, base_addr, kexit_info, dest_offset, offset, size POP %jump(wcopy_within_bounds) @@ -324,24 +333,22 @@ mcopy_with_overlap: // For this, we need to update `offset` and `dest_offset` to their final position, corresponding // to `x + size - min(32, size)`. - // stack: shift=min(size, 32), segment, context, kexit_info, dest_offset, offset, size + // stack: shift=min(size, 32), base_addr, kexit_info, dest_offset, offset, size DUP1 - // stack: shift, shift, segment, context, kexit_info, dest_offset, offset, size - DUP8 DUP8 ADD - // stack: offset+size, shift, shift, segment, context, kexit_info, dest_offset, offset, size + // stack: shift, shift, base_addr, kexit_info, dest_offset, offset, size + DUP7 DUP7 ADD + // stack: offset+size, shift, shift, base_addr, kexit_info, dest_offset, offset, size SUB - // stack: offset'=offset+size-shift, shift, segment, context, kexit_info, dest_offset, offset, size - SWAP5 DUP8 ADD - // stack: dest_offset+size, shift, segment, context, kexit_info, offset', offset, size + // stack: offset'=offset+size-shift, shift, base_addr, kexit_info, dest_offset, offset, size + SWAP4 DUP7 ADD + // stack: dest_offset+size, shift, base_addr, kexit_info, offset', offset, size SUB - // stack: dest_offset'=dest_offset+size-shift, segment, context, kexit_info, offset', offset, size + // stack: dest_offset'=dest_offset+size-shift, base_addr, kexit_info, offset', offset, size - %stack (next_dst_offset, segment, context, kexit_info, new_offset, offset, size) -> - (context, segment, new_offset, segment, next_dst_offset, context, size, wcopy_after, kexit_info) - %build_address // SRC - SWAP3 - %build_address // DST - // stack: DST, SRC, size, wcopy_after, kexit_info + DUP2 ADD // DST + // stack: DST, base_addr, kexit_info, new_offset, offset, size + SWAP3 ADD // SRC + %stack (SRC, kexit_info, DST, offset, size) -> (DST, SRC, size, wcopy_after, kexit_info) %jump(memcpy_bytes_backwards) mcopy_empty: diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm index ff7610f6d..e754b77a9 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm @@ -31,6 +31,7 @@ global process_type_0_txn: %decode_and_store_gas_limit %decode_and_store_to %decode_and_store_value +global debug_before_storing_txn_field_data_len: %decode_and_store_data // stack: rlp_addr, nonce_addr, retdest DUP1 diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index bafee07ae..0749f7fa9 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -679,8 +679,7 @@ impl GenerationState { .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); self.state_pointers - .remove(&addr) - .ok_or(ProgramError::ProverInputError(InvalidInput))?; + .remove(&addr); Ok(U256::from(ptr / ACCOUNTS_LINKED_LIST_NODE_SIZE)) } diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 14de01f8c..7198b020e 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -323,7 +323,7 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ); } - if KERNEL.offset_name(pc) == "smt_hash_state" { + if KERNEL.offset_name(pc) == "smt_hash_state" || KERNEL.offset_name(pc) == "sys_sstore"{ let mem = state .get_generation_state() .memory diff --git a/smt_trie/src/code.rs b/smt_trie/src/code.rs index dd6b142b9..bfed04a7d 100644 --- a/smt_trie/src/code.rs +++ b/smt_trie/src/code.rs @@ -10,6 +10,8 @@ use crate::utils::hashout2u; pub fn hash_contract_bytecode(mut code: Vec) -> HashOut { poseidon_pad_byte_vec(&mut code); + println!("code bytes = {:?}", code); + println!("hash = {:?}", hashout2u(poseidon_hash_padded_byte_vec(code.clone()))); poseidon_hash_padded_byte_vec(code) } @@ -37,6 +39,7 @@ pub fn poseidon_hash_padded_byte_vec(bytes: Vec) -> HashOut { pub fn poseidon_pad_byte_vec(bytes: &mut Vec) { bytes.push(0x01); + println!("code len = {:?}", bytes.len()); while bytes.len() % 56 != 0 { bytes.push(0x00); } From 6d550d282be98e037bcbf3db201c6563c6e4f85e Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Fri, 25 Oct 2024 18:56:46 +0200 Subject: [PATCH 31/60] merge_continuation --- evm_arithmetization/Cargo.toml | 2 +- .../benches/fibonacci_25m_gas.rs | 170 +++++++++++++++--- .../src/cpu/kernel/asm/account_code.asm | 6 +- .../linked_list/type2/state_linked_list.asm | 2 +- .../src/cpu/kernel/asm/main.asm | 2 +- .../src/cpu/kernel/constants/mod.rs | 15 -- .../src/cpu/kernel/interpreter.rs | 1 + .../src/cpu/kernel/tests/account_code.rs | 157 ++++++++++------ .../src/cpu/kernel/tests/balance.rs | 14 ++ .../src/cpu/kernel/tests/init_exc_stop.rs | 67 ++++--- .../src/cpu/kernel/tests/mpt/mod.rs | 33 ++++ .../src/generation/linked_list.rs | 8 +- evm_arithmetization/src/generation/mod.rs | 4 + evm_arithmetization/src/generation/mpt.rs | 15 +- .../src/generation/prover_input.rs | 15 +- .../src/generation/segments.rs | 3 +- evm_arithmetization/src/generation/state.rs | 65 +++---- evm_arithmetization/src/testing_utils.rs | 22 ++- evm_arithmetization/tests/erc20_type2.rs | 14 +- evm_arithmetization/tests/global_exit_root.rs | 2 +- 20 files changed, 419 insertions(+), 198 deletions(-) diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index 0eb5457ad..f5dfec2f2 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -61,7 +61,7 @@ hex.workspace = true ripemd.workspace = true [features] -default = ["cdk_erigon"] +default = ["eth_mainnet"] asmtools = ["hex"] polygon_pos = [] cdk_erigon = ["smt_trie"] diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 2242b3049..a4b5b86b0 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -9,7 +9,8 @@ use std::str::FromStr; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; -use ethereum_types::{Address, H256, U256}; +use ethereum_types::BigEndianHash; +use ethereum_types::{Address, H160, H256, U256}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; @@ -17,9 +18,13 @@ use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::simulate_execution; use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, + beacon_roots_account_nibbles, update_beacon_roots_account_storage, }; +#[cfg(feature = "eth_mainnet")] +use evm_arithmetization::testing_utils::{ + beacon_roots_contract_from_storage, preinitialized_state_and_storage_tries, +}; +use evm_arithmetization::util::h2u; use evm_arithmetization::{Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -27,6 +32,12 @@ use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; +use plonky2::field::types::PrimeField64; +use smt_trie::code::hash_bytecode_u256; +use smt_trie::db::{Db, MemoryDb}; +use smt_trie::keys::{key_balance, key_code, key_code_length, key_nonce, key_storage}; +use smt_trie::smt::Smt; +use smt_trie::utils::hashout2u; type F = GoldilocksField; @@ -72,15 +83,19 @@ fn prepare_setup() -> anyhow::Result> { push1, 1, push1, 1, jumpdest, dup2, add, swap1, push4, 0, 0, 0, 4, jump, ]; let code_hash = keccak(code); + #[cfg(feature = "cdk_erigon")] + let code_hash = hash_bytecode_u256(code.to_vec()); let empty_trie_root = HashedPartialTrie::from(Node::Empty).hash(); + #[cfg(feature = "eth_mainnet")] let sender_account_before = AccountRlp { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, storage_root: empty_trie_root, code_hash: keccak(vec![]), }; + #[cfg(feature = "eth_mainnet")] let to_account_before = AccountRlp { nonce: 1.into(), balance: 0.into(), @@ -88,18 +103,62 @@ fn prepare_setup() -> anyhow::Result> { code_hash, }; - let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; - let mut beacon_roots_account_storage = storage_tries[0].1.clone(); - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; + #[cfg(feature = "cdk_erigon")] + let sender_account_before = AccountRlp { + nonce: 169.into(), + balance: U256::from_dec_str("999999999998417410153631615")?, + code_hash: hash_bytecode_u256(vec![]), + code_length: 0.into(), + }; + #[cfg(feature = "cdk_erigon")] + let to_account_before = AccountRlp { + nonce: 1.into(), + balance: 0.into(), + code_hash, + code_length: code.len().into(), + }; + + #[cfg(feature = "eth_mainnet")] + { + let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; + let mut beacon_roots_account_storage = storage_tries[0].1.clone(); + state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; - storage_tries.push((sender_state_key, Node::Empty.into())); - storage_tries.push((to_state_key, Node::Empty.into())); + storage_tries.push((sender_state_key, Node::Empty.into())); + storage_tries.push((to_state_key, Node::Empty.into())); + } + #[cfg(feature = "cdk_erigon")] + let mut smt_before: Smt = Smt::default(); + #[cfg(feature = "cdk_erigon")] + { + set_account( + &mut smt_before, + H160(sender), + &sender_account_before, + &HashMap::new(), + ); + set_account( + &mut smt_before, + H160(to), + &to_account_before, + &HashMap::new(), + ); + let sender_account_after = AccountRlp { + nonce: sender_account_before.nonce + 1, + balance: sender_account_before.balance, + ..sender_account_before + }; + } let tries_before = TrieInputs { + #[cfg(feature = "eth_mainnet")] state_trie: state_trie_before, + #[cfg(feature = "cdk_erigon")] + state_trie: smt_before, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), + #[cfg(feature = "eth_mainnet")] storage_tries, }; @@ -123,8 +182,16 @@ fn prepare_setup() -> anyhow::Result> { }; let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); - contract_code.insert(code_hash, code.to_vec()); + #[cfg(feature = "eth_mainnet")] + { + contract_code.insert(keccak(vec![]), vec![]); + contract_code.insert(code_hash, code.to_vec()); + } + #[cfg(feature = "cdk_erigon")] + { + contract_code.insert(hash_bytecode_u256(vec![]), vec![]); + contract_code.insert(code_hash, code.to_vec()); + } let sender_account_after = AccountRlp { balance: sender_account_before.balance - value - gas_used * block_metadata.block_base_fee, @@ -133,21 +200,43 @@ fn prepare_setup() -> anyhow::Result> { }; let to_account_after = to_account_before; + #[cfg(feature = "eth_mainnet")] let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; - - update_beacon_roots_account_storage( - &mut beacon_roots_account_storage, - block_metadata.block_timestamp, - block_metadata.parent_beacon_block_root, - )?; - let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - expected_state_trie_after.insert( - beacon_roots_account_nibbles(), - rlp::encode(&beacon_roots_account).to_vec(), - )?; + #[cfg(feature = "eth_mainnet")] + { + expected_state_trie_after + .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; + expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; + + update_beacon_roots_account_storage( + &mut beacon_roots_account_storage, + block_metadata.block_timestamp, + block_metadata.parent_beacon_block_root, + )?; + let beacon_roots_account = + beacon_roots_contract_from_storage(&beacon_roots_account_storage); + expected_state_trie_after.insert( + beacon_roots_account_nibbles(), + rlp::encode(&beacon_roots_account).to_vec(), + )?; + } + #[cfg(feature = "cdk_erigon")] + let mut expected_smt_after: Smt<_> = Smt::default(); + #[cfg(feature = "cdk_erigon")] + { + set_account::( + &mut expected_smt_after, + H160(sender), + &sender_account_after, + &HashMap::new(), + ); + set_account( + &mut expected_smt_after, + H160(to), + &to_account_after, + &HashMap::new(), + ); + } let receipt_0 = LegacyReceiptRlp { status: false, @@ -167,7 +256,10 @@ fn prepare_setup() -> anyhow::Result> { .into(); let trie_roots_after = TrieRoots { + #[cfg(feature = "eth_mainnet")] state_root: expected_state_trie_after.hash(), + #[cfg(feature = "cdk_erigon")] + state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), }; @@ -201,3 +293,31 @@ fn init_logger() { criterion_group!(benches, criterion_benchmark); criterion_main!(benches); + +fn set_account( + smt: &mut Smt, + addr: Address, + account: &AccountRlp, + storage: &HashMap, +) { + let key = key_balance(addr); + log::debug!( + "setting {:?} balance to {:?}, the key is {:?}", + addr, + account.balance, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); + smt.set(key_balance(addr), account.balance); + smt.set(key_nonce(addr), account.nonce); + smt.set(key_code(addr), account.code_hash); + let key = key_code_length(addr); + log::debug!( + "setting {:?} code length, the key is {:?}", + addr, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); + smt.set(key_code_length(addr), account.code_length); + for (&k, &v) in storage { + smt.set(key_storage(addr, k), v); + } +} diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 8f7f615d5..63c5b3abf 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -56,9 +56,9 @@ global extcodehash: #[cfg(feature = eth_mainnet)] { %macro ext_code_empty - %extcodehash - %eq_const(@EMPTY_STRING_HASH) -%endmacro + %extcodehash + %eq_const(@EMPTY_STRING_HASH) + %endmacro } #[cfg(feature = cdk_erigon)] { diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index 01b888df7..981673370 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -307,7 +307,7 @@ global debug_fail_1: global debug_fail_2: PANIC -key_found: +global key_found: // The key was already in the list. // stack: pred_ptr, key, retdest %increment diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 5f0252b82..caec7898e 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -267,7 +267,7 @@ global check_final_state_trie: %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) global debug_final_trie_hash: - %assert_eq + // %assert_eq // We don't need the trie data length here. POP diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index f0e2b63c9..fc3a65131 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -488,14 +488,6 @@ pub mod cancun_constants { code_hash: H256(BEACON_ROOTS_CONTRACT_CODE_HASH), }; - #[cfg(feature = "cdk_erigon")] - pub static BEACON_ROOTS_ACCOUNT: AccountRlp = AccountRlp { - nonce: U256::zero(), - balance: U256::zero(), - code_length: BEACON_ROOTS_CONTRACT_CODE_LEN_U256, - code_hash: H256(BEACON_ROOTS_CONTRACT_CODE_HASH), - }; - #[test] fn hashed() { assert_eq!( @@ -558,13 +550,6 @@ pub mod global_exit_root { )), code_hash: H256(GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH), }; - #[cfg(feature = "cdk_erigon")] - pub static GLOBAL_EXIT_ROOT_ACCOUNT: AccountRlp = AccountRlp { - nonce: U256::zero(), - balance: U256::zero(), - code_length: GLOBAL_EXIT_ROOT_CONTRACT_CODE_LEN_U256, - code_hash: H256(GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH), - }; #[test] fn hashed() { diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 84063ccb4..a8a3e86d5 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -117,6 +117,7 @@ pub(crate) struct ExtraSegmentData { pub(crate) ger_prover_inputs: Vec, pub(crate) trie_root_ptrs: TrieRootPtrs, pub(crate) jumpdest_table: Option>>, + #[cfg(feature = "eth_mainnet")] pub(crate) access_lists_ptrs: AccessLinkedListsPtrs, pub(crate) state_ptrs: StateLinkedListsPtrs, pub(crate) next_txn_index: usize, diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 8af4ed4a8..6b28dcfdd 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -9,6 +9,8 @@ use mpt_trie::partial_trie::{HashedPartialTrie, Node, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::hash::hash_types::RichField; use rand::{thread_rng, Rng}; +#[cfg(feature = "cdk_erigon")] +use smt_trie::{code::hash_bytecode_u256, smt::Smt, utils::hashout2u}; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata::{self, GasLimit}; @@ -16,9 +18,9 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; -use crate::generation::mpt::{ - load_linked_lists_and_txn_and_receipt_mpts, load_state_mpt, AccountRlp, -}; +use crate::generation::mpt::AccountRlp; +#[cfg(feature = "eth_mainnet")] +use crate::generation::mpt::{load_linked_lists_and_txn_and_receipt_mpts, load_state_mpt}; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -30,34 +32,63 @@ pub(crate) fn initialize_mpts( trie_inputs: &TrieInputs, ) { // Load all MPTs. - let (mut trie_root_ptrs, state_leaves, storage_leaves, trie_data) = - load_linked_lists_and_txn_and_receipt_mpts( - &mut interpreter.generation_state.state_ptrs.accounts, - &mut interpreter.generation_state.state_ptrs.storage, - trie_inputs, - ) - .expect("Invalid MPT data for preinitialization"); - - interpreter.generation_state.memory.contexts[0].segments - [Segment::AccountsLinkedList.unscale()] - .content = state_leaves; - interpreter.generation_state.memory.contexts[0].segments - [Segment::StorageLinkedList.unscale()] - .content = storage_leaves; - interpreter.generation_state.memory.contexts[0].segments[Segment::TrieData.unscale()].content = - trie_data.clone(); - interpreter.generation_state.trie_root_ptrs = trie_root_ptrs.clone(); - - if trie_root_ptrs.state_root_ptr.is_none() { - trie_root_ptrs.state_root_ptr = Some( - load_state_mpt( - &trie_inputs.trim(), - &mut interpreter.generation_state.memory.contexts[0].segments - [Segment::TrieData.unscale()] - .content, + #[cfg(feature = "eth_mainnet")] + { + let (mut trie_root_ptrs, state_leaves, storage_leaves, trie_data) = + load_linked_lists_and_txn_and_receipt_mpts( + &mut interpreter.generation_state.state_ptrs.accounts, + &mut interpreter.generation_state.state_ptrs.storage, + trie_inputs, ) - .expect("Invalid MPT data for preinitialization"), - ); + .expect("Invalid MPT data for preinitialization"); + + interpreter.generation_state.memory.contexts[0].segments + [Segment::AccountsLinkedList.unscale()] + .content = state_leaves; + interpreter.generation_state.memory.contexts[0].segments + [Segment::StorageLinkedList.unscale()] + .content = storage_leaves; + interpreter.generation_state.memory.contexts[0].segments[Segment::TrieData.unscale()] + .content = trie_data.clone(); + interpreter.generation_state.trie_root_ptrs = trie_root_ptrs.clone(); + + if trie_root_ptrs.state_root_ptr.is_none() { + trie_root_ptrs.state_root_ptr = Some( + load_state_mpt( + &trie_inputs.trim(), + &mut interpreter.generation_state.memory.contexts[0].segments + [Segment::TrieData.unscale()] + .content, + ) + .expect("Invalid MPT data for preinitialization"), + ); + } + + let mut to_set = vec![]; + if let Some(state_root_ptr) = trie_root_ptrs.state_root_ptr { + to_set.push((state_addr, state_root_ptr.into())); + } + to_set.extend([ + (txn_addr, trie_root_ptrs.txn_root_ptr.into()), + (receipts_addr, trie_root_ptrs.receipt_root_ptr.into()), + ]); + + interpreter.set_memory_multi_addresses(&to_set); + + for (i, data) in trie_data.iter().enumerate() { + let trie_addr = MemoryAddress::new(0, Segment::TrieData, i); + interpreter + .generation_state + .memory + .set(trie_addr, data.unwrap_or_default()); + } + } + + #[cfg(feature = "cdk_erigon")] + { + interpreter + .generation_state + .preinitialize_linked_lists(trie_inputs); } let accounts_len = Segment::AccountsLinkedList as usize @@ -113,25 +144,6 @@ pub(crate) fn initialize_mpts( MemoryAddress::new_bundle((GlobalMetadata::TransactionTrieRoot as usize).into()).unwrap(); let receipts_addr = MemoryAddress::new_bundle((GlobalMetadata::ReceiptTrieRoot as usize).into()).unwrap(); - - let mut to_set = vec![]; - if let Some(state_root_ptr) = trie_root_ptrs.state_root_ptr { - to_set.push((state_addr, state_root_ptr.into())); - } - to_set.extend([ - (txn_addr, trie_root_ptrs.txn_root_ptr.into()), - (receipts_addr, trie_root_ptrs.receipt_root_ptr.into()), - ]); - - interpreter.set_memory_multi_addresses(&to_set); - - for (i, data) in trie_data.iter().enumerate() { - let trie_addr = MemoryAddress::new(0, Segment::TrieData, i); - interpreter - .generation_state - .memory - .set(trie_addr, data.unwrap_or_default()); - } } // Stolen from `tests/mpt/insert.rs` @@ -145,9 +157,13 @@ pub(crate) fn prepare_interpreter( let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; let mut state_trie: HashedPartialTrie = HashedPartialTrie::from(Node::Empty); let trie_inputs = TrieInputs { + #[cfg(feature = "eth_mainnet")] state_trie: HashedPartialTrie::from(Node::Empty), + #[cfg(feature = "cdk_erigon")] + state_trie: Smt::default(), transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), + #[cfg(feature = "eth_mainnet")] storage_tries: vec![], }; @@ -172,7 +188,10 @@ pub(crate) fn prepare_interpreter( // so we have to ensure the pointer is valid. It's easiest to set it to 0, // which works as an empty node, since trie_data[0] = 0 = MPT_TYPE_EMPTY. trie_data.push(Some(H256::zero().into_uint())); + #[cfg(feature = "eth_mainnet")] trie_data.push(Some(account.code_hash.into_uint())); + #[cfg(feature = "cdk_erigon")] + trie_data.push(Some(account.code_hash)); let trie_data_len = trie_data.len().into(); interpreter.set_global_metadata_field(GlobalMetadata::TrieDataSize, trie_data_len); interpreter @@ -250,6 +269,7 @@ pub(crate) fn prepare_interpreter( } // Test account with a given code hash. +#[cfg(feature = "eth_mainnet")] fn test_account(code: &[u8]) -> AccountRlp { AccountRlp { nonce: U256::from(1111), @@ -259,6 +279,17 @@ fn test_account(code: &[u8]) -> AccountRlp { } } +// Test account with a given code hash. +#[cfg(feature = "cdk_erigon")] +fn test_account(code: &[u8]) -> AccountRlp { + AccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: hash_bytecode_u256(code.to_vec()), + code_length: code.len().into(), + } +} + fn random_code() -> Vec { let mut rng = thread_rng(); let num_bytes = rng.gen_range(0..1000); @@ -288,8 +319,17 @@ fn test_extcodesize() -> Result<()> { interpreter .push(U256::from_big_endian(address.as_bytes())) .expect("The stack should not overflow"); - interpreter.generation_state.inputs.contract_code = - HashMap::from([(keccak(&code), code.clone())]); + #[cfg(feature = "eth_mainnet")] + { + interpreter.generation_state.inputs.contract_code = + HashMap::from([(keccak(&code), code.clone())]); + } + #[cfg(feature = "cdk_erigon")] + { + interpreter.generation_state.inputs.contract_code = + HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); + } + interpreter.run()?; assert_eq!( @@ -362,8 +402,17 @@ fn test_extcodecopy() -> Result<()> { interpreter .push((0xDEADBEEFu64 + (1 << 32)).into()) .expect("The stack should not overflow"); // kexit_info - interpreter.generation_state.inputs.contract_code = - HashMap::from([(keccak(&code), code.clone())]); + #[cfg(feature = "eth_mainnet")] + { + interpreter.generation_state.inputs.contract_code = + HashMap::from([(keccak(&code), code.clone())]); + } + #[cfg(feature = "cdk_erigon")] + { + interpreter.generation_state.inputs.contract_code = + HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); + } + interpreter.run()?; assert!(interpreter.stack().is_empty()); @@ -460,6 +509,7 @@ fn prepare_interpreter_all_accounts( /// Tests an SSTORE within a code similar to the contract code in add11_yml. #[test] +#[cfg(feature = "eth_mainnet")] fn sstore() -> Result<()> { // We take the same `to` account as in add11_yml. let addr = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); @@ -550,6 +600,7 @@ fn sstore() -> Result<()> { /// Tests an SLOAD within a code similar to the contract code in add11_yml. #[test] +#[cfg(feature = "eth_mainnet")] fn sload() -> Result<()> { let addr = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); diff --git a/evm_arithmetization/src/cpu/kernel/tests/balance.rs b/evm_arithmetization/src/cpu/kernel/tests/balance.rs index fc4d63347..dc8eab845 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/balance.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/balance.rs @@ -11,6 +11,7 @@ use crate::generation::mpt::AccountRlp; use crate::Node; // Test account with a given code hash. +#[cfg(feature = "eth_mainnet")] fn test_account(balance: U256) -> AccountRlp { AccountRlp { nonce: U256::from(1111), @@ -20,6 +21,19 @@ fn test_account(balance: U256) -> AccountRlp { } } +// Test account with a given code hash. +#[cfg(feature = "cdk_erigon")] +fn test_account(balance: U256) -> AccountRlp { + use smt_trie::code::hash_bytecode_u256; + + AccountRlp { + nonce: U256::from(1111), + balance, + code_hash: hash_bytecode_u256(vec![0x01, 0x00]), + code_length: 2.into(), + } +} + #[test] fn test_balance() -> Result<()> { let mut rng = thread_rng(); diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs index 2dea58b55..beb7379e6 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -1,18 +1,24 @@ use std::collections::HashMap; -use ethereum_types::U256; +use ethereum_types::{BigEndianHash, U256}; use keccak_hash::{keccak, H256}; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::field::types::Field; +use smt_trie::code::hash_bytecode_u256; +use smt_trie::db::MemoryDb; +use smt_trie::smt::Smt; +use smt_trie::utils::hashout2u; use crate::cpu::kernel::{aggregator::KERNEL, interpreter::Interpreter}; use crate::generation::{ state::State, TrieInputs, NUM_EXTRA_CYCLES_AFTER, NUM_EXTRA_CYCLES_BEFORE, }; use crate::memory::segments::Segment; +use crate::testing_utils::init_logger; +#[cfg(feature = "eth_mainnet")] use crate::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, + beacon_roots_account_nibbles, beacon_roots_contract_from_storage, preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use crate::witness::{memory::MemoryAddress, state::RegistersState}; @@ -44,35 +50,53 @@ fn test_init_exc_stop() { ..Default::default() }; - let (state_trie_before, storage_tries) = preinitialized_state_and_storage_tries().unwrap(); - let mut beacon_roots_account_storage = storage_tries[0].1.clone(); + #[cfg(feature = "eth_mainnet")] + { + let (state_trie_before, storage_tries) = preinitialized_state_and_storage_tries().unwrap(); + let mut beacon_roots_account_storage = storage_tries[0].1.clone(); + } + + #[cfg(feature = "cdk_erigon")] + let state_trie_before = Smt::default(); + let transactions_trie = HashedPartialTrie::from(Node::Empty); let receipts_trie = HashedPartialTrie::from(Node::Empty); - let expected_state_trie_after = { - update_beacon_roots_account_storage( - &mut beacon_roots_account_storage, - block_metadata.block_timestamp, - block_metadata.parent_beacon_block_root, - ) - .unwrap(); - let beacon_roots_account = - beacon_roots_contract_from_storage(&beacon_roots_account_storage); - - let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after - .insert( - beacon_roots_account_nibbles(), - rlp::encode(&beacon_roots_account).to_vec(), + #[cfg(feature = "eth_mainnet")] + { + let expected_state_trie_after = { + update_beacon_roots_account_storage( + &mut beacon_roots_account_storage, + block_metadata.block_timestamp, + block_metadata.parent_beacon_block_root, ) .unwrap(); - expected_state_trie_after - }; + let beacon_roots_account = + beacon_roots_contract_from_storage(&beacon_roots_account_storage); + + let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); + expected_state_trie_after + .insert( + beacon_roots_account_nibbles(), + rlp::encode(&beacon_roots_account).to_vec(), + ) + .unwrap(); + expected_state_trie_after + }; + } + #[cfg(feature = "cdk_erigon")] + let expected_state_trie_after: Smt = Smt::default(); let mut contract_code = HashMap::new(); + #[cfg(feature = "eth_mainnet")] contract_code.insert(keccak(vec![]), vec![]); + #[cfg(feature = "cdk_erigon")] + contract_code.insert(hash_bytecode_u256(vec![]), vec![]); let trie_roots_after = TrieRoots { + #[cfg(feature = "cdk_erigon")] + state_root: H256::from_uint(&hashout2u(expected_state_trie_after.root)), + #[cfg(feature = "eth_mainnet")] state_root: expected_state_trie_after.hash(), transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), @@ -86,6 +110,7 @@ fn test_init_exc_stop() { state_trie: state_trie_before, transactions_trie, receipts_trie, + #[cfg(feature = "eth_mainnet")] storage_tries, }, trie_roots_after, diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 5ebc0f4a5..1207eab84 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -35,6 +35,7 @@ pub(crate) fn nibbles_count>(v: T, count: usize) -> Nibbles { } } +#[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_1() -> AccountRlp { AccountRlp { nonce: U256::from(1111), @@ -44,6 +45,7 @@ pub(crate) fn test_account_1() -> AccountRlp { } } +#[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_1_empty_storage() -> AccountRlp { AccountRlp { nonce: U256::from(1111), @@ -53,6 +55,26 @@ pub(crate) fn test_account_1_empty_storage() -> AccountRlp { } } +#[cfg(feature = "cdk_erigon")] +pub(crate) fn test_account_1() -> AccountRlp { + AccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: U256::from(4444), + code_length: 0.into(), + } +} + +#[cfg(feature = "cdk_erigon")] +pub(crate) fn test_account_1_empty_storage() -> AccountRlp { + AccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: U256::from(4444), + code_length: 0.into(), + } +} + pub(crate) fn test_account_1_rlp() -> Vec { rlp::encode(&test_account_1()).to_vec() } @@ -61,6 +83,7 @@ pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { rlp::encode(&test_account_1_empty_storage()).to_vec() } +#[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_2() -> AccountRlp { AccountRlp { nonce: U256::from(5555), @@ -70,6 +93,16 @@ pub(crate) fn test_account_2() -> AccountRlp { } } +#[cfg(feature = "cdk_erigon")] +pub(crate) fn test_account_2() -> AccountRlp { + AccountRlp { + nonce: U256::from(5555), + balance: U256::from(6666), + code_hash: U256::from(8888), + code_length: 0.into(), + } +} + pub(crate) fn test_account_2_rlp() -> Vec { rlp::encode(&test_account_2()).to_vec() } diff --git a/evm_arithmetization/src/generation/linked_list.rs b/evm_arithmetization/src/generation/linked_list.rs index a8a9febb0..45a395c7c 100644 --- a/evm_arithmetization/src/generation/linked_list.rs +++ b/evm_arithmetization/src/generation/linked_list.rs @@ -18,11 +18,11 @@ pub(crate) struct AccessLinkedListsPtrs { /// Each entry contains the pair (key, ptr) where key is the (hashed) key /// of an account in the accounts linked list, and ptr is the respective /// node address in memory. - pub(crate) accounts: BTreeMap, + pub(crate) accounts_pointers: BTreeMap, /// Each entry contains the pair ((account_key, slot_key), ptr) where /// account_key is the (hashed) key of an account, slot_key is the slot /// key, and ptr is the respective node address in memory. - pub(crate) storage: BTreeMap<(U256, U256), usize>, + pub(crate) storage_pointers: BTreeMap<(U256, U256), usize>, } // Provides quick access to pointers that reference the memory location @@ -33,11 +33,11 @@ pub(crate) struct StateLinkedListsPtrs { /// Each entry contains the pair (key, ptr) where key is the (hashed) key /// of an account in the accounts linked list, and ptr is the respective /// node address in memory. - pub(crate) accounts: BTreeMap, + pub(crate) accounts_pointers: BTreeMap, /// Each entry contains the pair ((account_key, slot_key), ptr) where /// account_key is the (hashed) key of an account, slot_key is the slot /// key, and ptr is the respective node address in memory. - pub(crate) storage: BTreeMap<(U256, U256), usize>, + pub(crate) storage_pointers: BTreeMap<(U256, U256), usize>, } // Provides quick access to pointers that reference the memory location diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index e9689e20e..f63018cfe 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -689,10 +689,14 @@ pub(crate) fn collect_debug_tries( .inspect_err(|e| error!("failed to retrieve state trie pointer: {e:?}")) .ok()?; + #[cfg(feature = "eth_mainnet")] let state_trie = get_state_trie::(&state.memory, state_trie_ptr) .inspect_err(|e| error!("unable to retrieve state trie for debugging purposes: {e:?}")) .ok()?; + #[cfg(feature = "cdk_erigon")] + let state_trie = HashedPartialTrie::default(); + let txn_trie_ptr = u256_to_usize( state .memory diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index c032730c3..466f16a04 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -36,7 +36,7 @@ pub struct AccountRlp { pub nonce: U256, pub balance: U256, pub code_length: U256, - pub code_hash: H256, + pub code_hash: U256, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] @@ -58,11 +58,13 @@ impl Default for AccountRlp { } #[cfg(feature = "cdk_erigon")] fn default() -> Self { + use smt_trie::code::hash_bytecode_u256; + Self { nonce: U256::zero(), balance: U256::zero(), + code_hash: hash_bytecode_u256(vec![]), code_length: U256::zero(), - code_hash: keccak([]), } } } @@ -437,7 +439,8 @@ fn get_state_and_storage_leaves( state_leaves.push(Some(addr_key)); // Set `value_ptr_ptr`. state_leaves.push(Some(trie_data.len().into())); - // Push something on the original `value_ptr_ptr` (to be set later in the kernel). + // Push something on the original `value_ptr_ptr` (to be set later in the + // kernel). state_leaves.push(Some(0.into())); // Set the next node as the initial node. state_leaves.push(Some((Segment::AccountsLinkedList as usize).into())); @@ -561,9 +564,11 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( trie_inputs: &TrieInputs, ) -> Result { let mut state_leaves = - empty_list_mem::(Segment::AccountsLinkedList as usize).to_vec(); + empty_list_mem::(Segment::AccountsLinkedList as usize) + .to_vec(); let mut storage_leaves = - empty_list_mem::(Segment::StorageLinkedList as usize).to_vec(); + empty_list_mem::(Segment::StorageLinkedList as usize) + .to_vec(); let mut trie_data = vec![Some(U256::zero())]; let storage_tries_by_state_key = trie_inputs .storage_tries diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 91dacf41e..0cf3842f2 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -419,7 +419,7 @@ impl GenerationState { "state ll = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) ); - log::debug!("state btree = {:#?}", self.state_ptrs); + log::debug!("state btree = {:#?}", self.inputs.trimmed_tries.state_trie); log::debug!( "input state popopo = {}", self.inputs.trimmed_tries.state_trie @@ -620,13 +620,14 @@ impl GenerationState { fn run_next_insert_state(&mut self, input_fn: &ProverInputFn) -> Result { let key = stack_peek(self, 0)?; let (&pred_key, &pred_ptr) = self - .state_ptrs + .state_pointers + .state .range(..=key) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); if pred_key != key && input_fn.0[1].as_str() == "insert_state" { - self.state_ptrs.insert( + self.state_pointers.state.insert( key, u256_to_usize( self.memory @@ -696,15 +697,17 @@ impl GenerationState { log::debug!( "los que viene antes: = {:?}", - self.state_ptrs.range(..addr).next_back() + self.state_pointers.state.range(..addr).next_back() ); let (_, &ptr) = self - .state_ptrs + .state_pointers + .state .range(..addr) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); - self.state_ptrs + self.state_pointers + .state .remove(&addr) .ok_or(ProgramError::ProverInputError(InvalidInput))?; diff --git a/evm_arithmetization/src/generation/segments.rs b/evm_arithmetization/src/generation/segments.rs index eaf52a828..a3ac4057b 100644 --- a/evm_arithmetization/src/generation/segments.rs +++ b/evm_arithmetization/src/generation/segments.rs @@ -124,8 +124,9 @@ fn build_segment_data( trie_root_ptrs: interpreter.generation_state.trie_root_ptrs.clone(), jumpdest_table: interpreter.generation_state.jumpdest_table.clone(), next_txn_index: interpreter.generation_state.next_txn_index, - state: interpreter.generation_state.state_pointers.clone(), + state_ptrs: interpreter.generation_state.state_pointers.clone(), }, + opcode_counts: interpreter.opcode_count.clone(), } } diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 0506e0051..ca2d3d27a 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::mem::size_of; use anyhow::{anyhow, bail}; @@ -399,12 +399,13 @@ pub struct GenerationState { pub(crate) jumpdest_table: Option>>, /// Provides quick access to pointers that reference the location - /// of either and account or a slot in the respective access list. + /// of either an account or a slot in the respective access list. pub(crate) access_lists_ptrs: AccessLinkedListsPtrs, - /// Provides quick access to pointers that reference the memory location of - /// either and account or a slot in the respective access list. - pub(crate) state_ptrs: StateLinkedListsPtrs, + /// Provides quick access to pointers that reference the location + /// of either an account or a slot in the respective linked list. + #[cfg(feature = "eth_mainnet")] + pub(crate) state_pointers: StateLinkedListsPtrs, } impl GenerationState { @@ -435,8 +436,8 @@ impl GenerationState { fn preinitialize_linked_lists(&mut self, trie_inputs: &TrieInputs) { let generation_state = self.get_mut_generation_state(); let (state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( - &mut generation_state.accounts_pointers, - &mut generation_state.storage_pointers, + &mut generation_state.state_pointers.accounts_pointers, + &mut generation_state.state_pointers.storage_pointers, trie_inputs, ) .expect("Invalid MPT data for preinitialization"); @@ -459,7 +460,7 @@ impl GenerationState { } #[cfg(feature = "cdk_erigon")] - fn preinitialize_linked_lists(&mut self, trie_inputs: &TrieInputs) { + pub(crate) fn preinitialize_linked_lists(&mut self, trie_inputs: &TrieInputs) { let generation_state = self.get_mut_generation_state(); let mut smt_data = vec![Some(U256::zero()); 2]; // For empty hash node. let mut state_linked_list_data = @@ -469,7 +470,7 @@ impl GenerationState { .state_trie .load_linked_list_data::<{ Segment::AccountsLinkedList as usize }>( &mut state_linked_list_data, - &mut self.state_ptrs.accounts, + &mut self.state_pointers.state, ); self.memory.insert_preinitialized_segment( @@ -514,7 +515,10 @@ impl GenerationState { }, jumpdest_table: None, access_lists_ptrs: AccessLinkedListsPtrs::default(), - state_ptrs: StateLinkedListsPtrs::default(), + state_pointers: StateLinkedListsPtrs { + accounts_pointers: BTreeMap::new(), + storage_pointers: BTreeMap::new(), + }, ger_prover_inputs, }; let trie_root_ptrs = state.preinitialize_trie_data_and_get_trie_ptrs(&inputs.tries); @@ -542,7 +546,9 @@ impl GenerationState { }, jumpdest_table: None, access_lists_ptrs: AccessLinkedListsPtrs::default(), - state_ptrs: StateLinkedListsPtrs::default(), + state_pointers: StateLinkedListsPtrs { + state: BTreeMap::new(), + }, ger_prover_inputs, }; let trie_root_ptrs = state.preinitialize_trie_data_and_get_trie_ptrs(&inputs.tries); @@ -558,8 +564,6 @@ impl GenerationState { ) -> Result { let mut state = Self { inputs: trimmed_inputs.clone(), - state_ptrs: segment_data.extra_data.state_ptrs.clone(), - access_lists_ptrs: segment_data.extra_data.access_lists_ptrs.clone(), ..Default::default() }; @@ -667,7 +671,6 @@ impl GenerationState { } /// Clones everything but the traces. - #[cfg(feature = "eth_mainnet")] pub(crate) fn soft_clone(&self) -> GenerationState { Self { inputs: self.inputs.clone(), // inputs have already been trimmed here @@ -688,33 +691,7 @@ impl GenerationState { }, jumpdest_table: None, access_lists_ptrs: self.access_lists_ptrs.clone(), - state_ptrs: self.state_ptrs.clone(), - } - } - - /// Clones everything but the traces. - #[cfg(feature = "cdk_erigon")] - pub(crate) fn soft_clone(&self) -> GenerationState { - Self { - inputs: self.inputs.clone(), // inputs have already been trimmed here - registers: self.registers, - memory: self.memory.clone(), - traces: Traces::default(), - next_txn_index: 0, - stale_contexts: Vec::new(), - rlp_prover_inputs: self.rlp_prover_inputs.clone(), - state_key_to_address: self.state_key_to_address.clone(), - bignum_modmul_result_limbs: self.bignum_modmul_result_limbs.clone(), - withdrawal_prover_inputs: self.withdrawal_prover_inputs.clone(), - ger_prover_inputs: self.ger_prover_inputs.clone(), - trie_root_ptrs: TrieRootPtrs { - state_root_ptr: Some(0), - txn_root_ptr: 0, - receipt_root_ptr: 0, - }, - jumpdest_table: None, - access_lists_ptrs: self.access_lists_ptrs.clone(), - state_ptrs: self.state_ptrs.clone(), + state_pointers: self.state_pointers.clone(), } } @@ -732,7 +709,7 @@ impl GenerationState { .clone_from(&segment_data.extra_data.trie_root_ptrs); self.jumpdest_table .clone_from(&segment_data.extra_data.jumpdest_table); - self.state_ptrs + self.state_pointers .clone_from(&segment_data.extra_data.state_ptrs); self.access_lists_ptrs .clone_from(&segment_data.extra_data.access_lists_ptrs); @@ -760,10 +737,10 @@ impl GenerationState { .clone_from(&segment_data.extra_data.trie_root_ptrs); self.jumpdest_table .clone_from(&segment_data.extra_data.jumpdest_table); + self.state_pointers + .clone_from(&segment_data.extra_data.state_ptrs); self.access_lists_ptrs .clone_from(&segment_data.extra_data.access_lists_ptrs); - self.state_ptrs - .clone_from(&segment_data.extra_data.state_ptrs); self.next_txn_index = segment_data.extra_data.next_txn_index; self.registers = RegistersState { program_counter: self.registers.program_counter, diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index 8179fafd9..f581f8b25 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -10,7 +10,10 @@ use mpt_trie::{ nibbles::Nibbles, partial_trie::{HashedPartialTrie, Node, PartialTrie}, }; -use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2::{ + field::goldilocks_field::GoldilocksField, util::serialization::gate_serialization::default, +}; +use smt_trie::smt::Smt; pub use crate::cpu::kernel::cancun_constants::*; pub use crate::cpu::kernel::constants::global_exit_root::*; @@ -90,6 +93,7 @@ pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> A /// Returns an initial state trie containing the beacon roots and global exit /// roots contracts, along with their storage tries. +#[cfg(feature = "eth_mainnet")] pub fn preinitialized_state_and_storage_tries( ) -> anyhow::Result<(HashedPartialTrie, Vec<(H256, HashedPartialTrie)>)> { let mut state_trie = HashedPartialTrie::from(Node::Empty); @@ -165,13 +169,6 @@ pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp } } -pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { - AccountRlp { - storage_root: storage_trie.hash(), - ..Default::default() - } -} - fn empty_payload() -> Result { // Set up default block metadata let block_metadata = BlockMetadata { @@ -188,10 +185,12 @@ fn empty_payload() -> Result { // Initialize an empty state trie and storage tries let state_trie_before = HashedPartialTrie::from(crate::Node::Empty); + #[cfg(feature = "eth_mainnet")] let storage_tries = Vec::new(); let checkpoint_state_trie_root = state_trie_before.hash(); // Prepare the tries without any transactions or receipts + #[cfg(feature = "eth_mainnet")] let tries_before = TrieInputs { state_trie: state_trie_before.clone(), storage_tries: storage_tries.clone(), @@ -199,6 +198,13 @@ fn empty_payload() -> Result { receipts_trie: HashedPartialTrie::from(crate::Node::Empty), }; + #[cfg(feature = "cdk_erigon")] + let tries_before = TrieInputs { + state_trie: Smt::default(), + transactions_trie: HashedPartialTrie::from(crate::Node::Empty), + receipts_trie: HashedPartialTrie::from(crate::Node::Empty), + }; + // The expected state trie after execution remains the same as before let expected_state_trie_after = state_trie_before; diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index 71c9e48cd..baf5f9039 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -15,11 +15,7 @@ use evm_arithmetization::testing_utils::ADDRESS_SCALABLE_L2; use evm_arithmetization::testing_utils::LAST_BLOCK_STORAGE_POS; use evm_arithmetization::testing_utils::STATE_ROOT_STORAGE_POS; use evm_arithmetization::testing_utils::TIMESTAMP_STORAGE_POS; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, create_account_storage, init_logger, - preinitialized_state_and_storage_tries, sd2u, update_beacon_roots_account_storage, -}; -use evm_arithmetization::util::h2u; +use evm_arithmetization::testing_utils::{init_logger, sd2u}; use evm_arithmetization::verifier::testing::verify_all_proofs; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; @@ -29,7 +25,6 @@ use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; use plonky2::field::types::PrimeField64; -use plonky2::hash::hash_types::RichField; use plonky2::plonk::config::KeccakGoldilocksConfig; use plonky2::util::timing::TimingTree; use smt_trie::code::hash_bytecode_u256; @@ -301,7 +296,7 @@ fn giver_account() -> AccountRlp { AccountRlp { nonce: 1.into(), balance: 0.into(), - code_hash: H256::from_uint(&hash_bytecode_u256(code)), + code_hash: hash_bytecode_u256(code), code_length: len.into(), } } @@ -312,7 +307,7 @@ fn token_account() -> AccountRlp { AccountRlp { nonce: 1.into(), balance: 0.into(), - code_hash: H256::from_uint(&hash_bytecode_u256(code)), + code_hash: hash_bytecode_u256(code), code_length: len.into(), } } @@ -364,7 +359,8 @@ fn set_account( ); smt.set(key_balance(addr), account.balance); smt.set(key_nonce(addr), account.nonce); - smt.set(key_code(addr), h2u(account.code_hash)); + log::debug!("account code {:?}", account.code_hash); + smt.set(key_code(addr), account.code_hash); let key = key_code_length(addr); log::debug!( "setting {:?} code length, the key is {:?}", diff --git a/evm_arithmetization/tests/global_exit_root.rs b/evm_arithmetization/tests/global_exit_root.rs index b7e82c7a0..3aa4cc601 100644 --- a/evm_arithmetization/tests/global_exit_root.rs +++ b/evm_arithmetization/tests/global_exit_root.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "cdk_erigon")] +#![cfg(feature = "eth_mainnet")] use std::collections::HashMap; use std::time::Duration; From 7e269d101f746bd49eaae6a535cf8a00ca876b10 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 29 Oct 2024 09:29:56 +0100 Subject: [PATCH 32/60] Continue changes/very slight cleanup --- evm_arithmetization/Cargo.toml | 2 +- .../benches/fibonacci_25m_gas.rs | 27 +++-- .../asm/linked_list/accounts_linked_list.asm | 4 +- .../src/cpu/kernel/asm/main.asm | 2 +- .../src/cpu/kernel/assembler.rs | 2 +- .../src/cpu/kernel/interpreter.rs | 4 +- .../src/cpu/kernel/tests/account_code.rs | 64 +++++------ .../src/cpu/kernel/tests/init_exc_stop.rs | 53 ++++----- .../src/cpu/kernel/tests/mpt/linked_list.rs | 27 +++-- .../src/generation/linked_list.rs | 4 +- evm_arithmetization/src/generation/mpt.rs | 1 + .../src/generation/prover_input.rs | 103 +++++++++++------- .../src/generation/segments.rs | 50 +-------- evm_arithmetization/src/generation/state.rs | 46 ++------ evm_arithmetization/src/testing_utils.rs | 9 ++ 15 files changed, 190 insertions(+), 208 deletions(-) diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index f5dfec2f2..0eb5457ad 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -61,7 +61,7 @@ hex.workspace = true ripemd.workspace = true [features] -default = ["eth_mainnet"] +default = ["cdk_erigon"] asmtools = ["hex"] polygon_pos = [] cdk_erigon = ["smt_trie"] diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index a4b5b86b0..3a8b60c38 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -9,8 +9,9 @@ use std::str::FromStr; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; -use ethereum_types::BigEndianHash; -use ethereum_types::{Address, H160, H256, U256}; +use ethereum_types::{Address, H256, U256}; +#[cfg(feature = "cdk_erigon")] +use ethereum_types::{BigEndianHash, H160}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; @@ -24,6 +25,7 @@ use evm_arithmetization::testing_utils::{ use evm_arithmetization::testing_utils::{ beacon_roots_contract_from_storage, preinitialized_state_and_storage_tries, }; +#[cfg(feature = "cdk_erigon")] use evm_arithmetization::util::h2u; use evm_arithmetization::{Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; @@ -32,12 +34,16 @@ use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; +#[cfg(feature = "cdk_erigon")] use plonky2::field::types::PrimeField64; -use smt_trie::code::hash_bytecode_u256; -use smt_trie::db::{Db, MemoryDb}; -use smt_trie::keys::{key_balance, key_code, key_code_length, key_nonce, key_storage}; -use smt_trie::smt::Smt; -use smt_trie::utils::hashout2u; +#[cfg(feature = "cdk_erigon")] +use smt_trie::{ + code::hash_bytecode_u256, + db::{Db, MemoryDb}, + keys::{key_balance, key_code, key_code_length, key_nonce, key_storage}, + smt::Smt, + utils::hashout2u, +}; type F = GoldilocksField; @@ -118,10 +124,12 @@ fn prepare_setup() -> anyhow::Result> { code_length: code.len().into(), }; + #[cfg(feature = "eth_mainnet")] + let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; + #[cfg(feature = "eth_mainnet")] + let mut beacon_roots_account_storage = storage_tries[0].1.clone(); #[cfg(feature = "eth_mainnet")] { - let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; - let mut beacon_roots_account_storage = storage_tries[0].1.clone(); state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; @@ -294,6 +302,7 @@ fn init_logger() { criterion_group!(benches, criterion_benchmark); criterion_main!(benches); +#[cfg(feature = "cdk_erigon")] fn set_account( smt: &mut Smt, addr: Address, diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm index 3c9416c91..7acb6a161 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm @@ -386,11 +386,11 @@ remove_all_slots_end: // stack: account_ptr %endmacro -%macro nonce_from_ptr: +%macro nonce_from_ptr %mload_trie_data %endmacro -%macro balance_from_ptr: +%macro balance_from_ptr %increment %mload_trie_data %endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index caec7898e..5f0252b82 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -267,7 +267,7 @@ global check_final_state_trie: %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) global debug_final_trie_hash: - // %assert_eq + %assert_eq // We don't need the trie data length here. POP diff --git a/evm_arithmetization/src/cpu/kernel/assembler.rs b/evm_arithmetization/src/cpu/kernel/assembler.rs index bd5bab3ee..4476a0c51 100644 --- a/evm_arithmetization/src/cpu/kernel/assembler.rs +++ b/evm_arithmetization/src/cpu/kernel/assembler.rs @@ -457,7 +457,7 @@ fn push_target_size(target: &PushTarget) -> u8 { match target { PushTarget::Literal(n) => u256_to_trimmed_be_bytes(n).len() as u8, PushTarget::Label(_) => BYTES_PER_OFFSET, - PushTarget::MacroLabel(v) => BYTES_PER_OFFSET, + PushTarget::MacroLabel(_) => BYTES_PER_OFFSET, PushTarget::MacroVar(v) => panic!("Variable not in a macro: {v}"), PushTarget::Constant(c) => panic!("Constant wasn't inlined: {c}"), } diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index a8a3e86d5..54cd84316 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -117,7 +117,6 @@ pub(crate) struct ExtraSegmentData { pub(crate) ger_prover_inputs: Vec, pub(crate) trie_root_ptrs: TrieRootPtrs, pub(crate) jumpdest_table: Option>>, - #[cfg(feature = "eth_mainnet")] pub(crate) access_lists_ptrs: AccessLinkedListsPtrs, pub(crate) state_ptrs: StateLinkedListsPtrs, pub(crate) next_txn_index: usize, @@ -486,9 +485,10 @@ impl Interpreter { /// Inserts a preinitialized segment, given as a [Segment], /// into the `preinitialized_segments` memory field. + #[cfg(feature = "eth_mainnet")] fn insert_preinitialized_segment(&mut self, segment: Segment, values: MemorySegmentState) { self.generation_state - .memory + .memorys .insert_preinitialized_segment(segment, values); } diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 6b28dcfdd..094dcd287 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -34,13 +34,15 @@ pub(crate) fn initialize_mpts( // Load all MPTs. #[cfg(feature = "eth_mainnet")] { - let (mut trie_root_ptrs, state_leaves, storage_leaves, trie_data) = - load_linked_lists_and_txn_and_receipt_mpts( - &mut interpreter.generation_state.state_ptrs.accounts, - &mut interpreter.generation_state.state_ptrs.storage, - trie_inputs, - ) - .expect("Invalid MPT data for preinitialization"); + let (state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( + &mut interpreter + .generation_state + .state_pointers + .accounts_pointers, + &mut interpreter.generation_state.state_pointers.storage_pointers, + trie_inputs, + ) + .expect("Invalid MPT data for preinitialization"); interpreter.generation_state.memory.contexts[0].segments [Segment::AccountsLinkedList.unscale()] @@ -50,30 +52,30 @@ pub(crate) fn initialize_mpts( .content = storage_leaves; interpreter.generation_state.memory.contexts[0].segments[Segment::TrieData.unscale()] .content = trie_data.clone(); - interpreter.generation_state.trie_root_ptrs = trie_root_ptrs.clone(); - - if trie_root_ptrs.state_root_ptr.is_none() { - trie_root_ptrs.state_root_ptr = Some( - load_state_mpt( - &trie_inputs.trim(), - &mut interpreter.generation_state.memory.contexts[0].segments - [Segment::TrieData.unscale()] - .content, - ) - .expect("Invalid MPT data for preinitialization"), - ); - } - - let mut to_set = vec![]; - if let Some(state_root_ptr) = trie_root_ptrs.state_root_ptr { - to_set.push((state_addr, state_root_ptr.into())); - } - to_set.extend([ - (txn_addr, trie_root_ptrs.txn_root_ptr.into()), - (receipts_addr, trie_root_ptrs.receipt_root_ptr.into()), - ]); - - interpreter.set_memory_multi_addresses(&to_set); + // interpreter.generation_state.trie_root_ptrs = trie_root_ptrs.clone(); + + // if trie_root_ptrs.state_root_ptr.is_none() { + // trie_root_ptrs.state_root_ptr = Some( + // load_state_mpt( + // &trie_inputs.trim(), + // &mut interpreter.generation_state.memory.contexts[0].segments + // [Segment::TrieData.unscale()] + // .content, + // ) + // .expect("Invalid MPT data for preinitialization"), + // ); + // } + + // let mut to_set = vec![]; + // if let Some(state_root_ptr) = trie_root_ptrs.state_root_ptr { + // to_set.push((state_addr, state_root_ptr.into())); + // } + // to_set.extend([ + // (txn_addr, trie_root_ptrs.txn_root_ptr.into()), + // (receipts_addr, trie_root_ptrs.receipt_root_ptr.into()), + // ]); + + // interpreter.set_memory_multi_addresses(&to_set); for (i, data) in trie_data.iter().enumerate() { let trie_addr = MemoryAddress::new(0, Segment::TrieData, i); diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs index beb7379e6..ba0d46311 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -5,10 +5,8 @@ use keccak_hash::{keccak, H256}; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::field::types::Field; -use smt_trie::code::hash_bytecode_u256; -use smt_trie::db::MemoryDb; -use smt_trie::smt::Smt; -use smt_trie::utils::hashout2u; +#[cfg(feature = "cdk_erigon")] +use smt_trie::{code::hash_bytecode_u256, db::MemoryDb, smt::Smt, utils::hashout2u}; use crate::cpu::kernel::{aggregator::KERNEL, interpreter::Interpreter}; use crate::generation::{ @@ -50,12 +48,6 @@ fn test_init_exc_stop() { ..Default::default() }; - #[cfg(feature = "eth_mainnet")] - { - let (state_trie_before, storage_tries) = preinitialized_state_and_storage_tries().unwrap(); - let mut beacon_roots_account_storage = storage_tries[0].1.clone(); - } - #[cfg(feature = "cdk_erigon")] let state_trie_before = Smt::default(); @@ -63,27 +55,30 @@ fn test_init_exc_stop() { let receipts_trie = HashedPartialTrie::from(Node::Empty); #[cfg(feature = "eth_mainnet")] - { - let expected_state_trie_after = { - update_beacon_roots_account_storage( - &mut beacon_roots_account_storage, - block_metadata.block_timestamp, - block_metadata.parent_beacon_block_root, + let (state_trie_before, storage_tries) = preinitialized_state_and_storage_tries().unwrap(); + #[cfg(feature = "eth_mainnet")] + let mut beacon_roots_account_storage = storage_tries[0].1.clone(); + #[cfg(feature = "eth_mainnet")] + let expected_state_trie_after = { + update_beacon_roots_account_storage( + &mut beacon_roots_account_storage, + block_metadata.block_timestamp, + block_metadata.parent_beacon_block_root, + ) + .unwrap(); + let beacon_roots_account = + beacon_roots_contract_from_storage(&beacon_roots_account_storage); + + let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); + expected_state_trie_after + .insert( + beacon_roots_account_nibbles(), + rlp::encode(&beacon_roots_account).to_vec(), ) .unwrap(); - let beacon_roots_account = - beacon_roots_contract_from_storage(&beacon_roots_account_storage); - - let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after - .insert( - beacon_roots_account_nibbles(), - rlp::encode(&beacon_roots_account).to_vec(), - ) - .unwrap(); - expected_state_trie_after - }; - } + expected_state_trie_after + }; + #[cfg(feature = "cdk_erigon")] let expected_state_trie_after: Smt = Smt::default(); 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 979a15170..8c56432a8 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs @@ -15,12 +15,14 @@ use crate::cpu::kernel::interpreter::Interpreter; use crate::generation::linked_list::testing::LinkedList; use crate::generation::linked_list::ACCOUNTS_LINKED_LIST_NODE_SIZE; use crate::generation::linked_list::STATE_LINKED_LIST_NODE_SIZE; +#[cfg(feature = "eth_mainnet")] use crate::generation::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use crate::memory::segments::Segment; use crate::witness::memory::MemoryAddress; use crate::witness::memory::MemorySegmentState; pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; +#[cfg(feature = "eth_mainnet")] pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; pub(crate) type StateLinkedList<'a> = LinkedList<'a, STATE_LINKED_LIST_NODE_SIZE>; @@ -110,19 +112,24 @@ fn test_list_iterator() -> Result<()> { .generation_state .memory .get_preinit_memory(Segment::StorageLinkedList); - let mut storage_list = - StorageLinkedList::from_mem_and_segment(&accounts_mem, Segment::StorageLinkedList).unwrap(); - let Some([addr, key, ptr, ptr_cpy, scaled_pos_1]) = storage_list.next() else { - return Err(anyhow::Error::msg("Couldn't get value")); - }; + #[cfg(feature = "eth_mainnet")] + { + let mut storage_list = + StorageLinkedList::from_mem_and_segment(&accounts_mem, Segment::StorageLinkedList) + .unwrap(); + let Some([addr, key, ptr, ptr_cpy, scaled_pos_1]) = storage_list.next() else { + return Err(anyhow::Error::msg("Couldn't get value")); + }; + assert_eq!(key, U256::zero()); + let Some([addr, _key, ptr, ptr_cpy, scaled_pos_1]) = storage_list.next() else { + return Err(anyhow::Error::msg("Couldn't get value")); + }; + } + assert_eq!(addr, U256::MAX); - assert_eq!(key, U256::zero()); assert_eq!(ptr, U256::zero()); assert_eq!(ptr_cpy, U256::zero()); assert_eq!(scaled_pos_1, (Segment::StorageLinkedList as usize).into()); - let Some([addr, _key, ptr, ptr_cpy, scaled_pos_1]) = storage_list.next() else { - return Err(anyhow::Error::msg("Couldn't get value")); - }; assert_eq!(addr, U256::MAX); assert_eq!(ptr, U256::zero()); assert_eq!(ptr_cpy, U256::zero()); @@ -214,6 +221,7 @@ fn test_insert_account() -> Result<()> { } #[test] +#[cfg(feature = "eth_mainnet")] fn test_insert_storage() -> Result<()> { init_logger(); @@ -489,6 +497,7 @@ fn test_insert_and_delete_accounts() -> Result<()> { } #[test] +#[cfg(feature = "eth_mainnet")] fn test_insert_and_delete_storage() -> Result<()> { init_logger(); diff --git a/evm_arithmetization/src/generation/linked_list.rs b/evm_arithmetization/src/generation/linked_list.rs index 45a395c7c..426c809a4 100644 --- a/evm_arithmetization/src/generation/linked_list.rs +++ b/evm_arithmetization/src/generation/linked_list.rs @@ -3,9 +3,8 @@ use std::collections::BTreeMap; use ethereum_types::U256; use serde::{Deserialize, Serialize}; -use crate::memory::segments::Segment; - pub const ACCOUNTS_LINKED_LIST_NODE_SIZE: usize = 4; +#[cfg(feature = "eth_mainnet")] pub const STORAGE_LINKED_LIST_NODE_SIZE: usize = 5; pub const STATE_LINKED_LIST_NODE_SIZE: usize = 4; @@ -71,6 +70,7 @@ pub(crate) mod testing { use anyhow::Result; use super::*; + use crate::memory::segments::Segment; use crate::util::u256_to_usize; use crate::witness::errors::ProgramError; use crate::witness::errors::ProverInputError::InvalidInput; diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 466f16a04..133ab35bf 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -10,6 +10,7 @@ use rlp::{Decodable, DecoderError, Encodable, PayloadInfo, Rlp, RlpStream}; use rlp_derive::{RlpDecodable, RlpEncodable}; use serde::{Deserialize, Serialize}; +#[cfg(feature = "eth_mainnet")] use super::linked_list::{ empty_list_mem, ACCOUNTS_LINKED_LIST_NODE_SIZE, STORAGE_LINKED_LIST_NODE_SIZE, }; diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 0cf3842f2..210039e8c 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -4,7 +4,9 @@ use std::collections::{BTreeSet, HashMap}; use std::str::FromStr; use anyhow::{bail, Error, Result}; -use ethereum_types::{BigEndianHash, H256, U256, U512}; +#[cfg(feature = "eth_mainnet")] +use ethereum_types::{BigEndianHash, H256}; +use ethereum_types::{U256, U512}; use itertools::Itertools; use num_bigint::BigUint; use plonky2::hash::hash_types::RichField; @@ -12,9 +14,9 @@ use serde::{Deserialize, Serialize}; #[cfg(test)] use super::linked_list::testing::{LinkedList, ADDRESSES_ACCESS_LIST_LEN}; -use super::linked_list::{ - AccessLinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD, STORAGE_LINKED_LIST_NODE_SIZE, -}; +#[cfg(feature = "eth_mainnet")] +use super::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; +use super::linked_list::{AccessLinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD}; #[cfg(feature = "eth_mainnet")] use super::mpt::load_state_mpt; use crate::cpu::kernel::cancun_constants::KZG_VERSIONED_HASH; @@ -143,19 +145,35 @@ impl GenerationState { .map(U256::from), "txn" => Ok(U256::from(self.trie_root_ptrs.txn_root_ptr)), "receipt" => Ok(U256::from(self.trie_root_ptrs.receipt_root_ptr)), - "trie_data_size" => Ok(self - .memory - .preinitialized_segments - .get(&Segment::TrieData) - .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) - .content - .len() - .max( - self.memory.contexts[0].segments[Segment::TrieData.unscale()] + "trie_data_size" => { + println!( + "length {}", + self.memory + .preinitialized_segments + .get(&Segment::TrieData) + .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) .content - .len(), - ) - .into()), + .len() + .max( + self.memory.contexts[0].segments[Segment::TrieData.unscale()] + .content + .len(), + ) + ); + Ok(self + .memory + .preinitialized_segments + .get(&Segment::TrieData) + .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) + .content + .len() + .max( + self.memory.contexts[0].segments[Segment::TrieData.unscale()] + .content + .len(), + ) + .into()) + } _ => Err(ProgramError::ProverInputError(InvalidInput)), } @@ -410,11 +428,12 @@ impl GenerationState { /// jump address. #[cfg(feature = "cdk_erigon")] fn run_linked_list(&mut self, input_fn: &ProverInputFn) -> Result { - let mem = self.memory.get_preinit_memory(Segment::AccountsLinkedList); - #[cfg(test)] { use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; + + let mem = self.memory.get_preinit_memory(Segment::AccountsLinkedList); + log::debug!( "state ll = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) @@ -504,13 +523,13 @@ impl GenerationState { let (&pred_addr, &ptr) = self .access_lists_ptrs - .accounts + .accounts_pointers .range(..=addr) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccessedAddresses as usize))); if pred_addr != addr { - self.access_lists_ptrs.accounts.insert( + self.access_lists_ptrs.accounts_pointers.insert( addr, u256_to_usize( self.memory @@ -529,12 +548,12 @@ impl GenerationState { let (_, &ptr) = self .access_lists_ptrs - .accounts + .accounts_pointers .range(..addr) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccessedAddresses as usize))); self.access_lists_ptrs - .accounts + .accounts_pointers .remove(&addr) .ok_or(ProgramError::ProverInputError(InvalidInput))?; @@ -549,12 +568,12 @@ impl GenerationState { let (&(pred_addr, pred_slot_key), &ptr) = self .access_lists_ptrs - .storage + .storage_pointers .range(..=(addr, key)) .next_back() .unwrap_or((&DUMMYHEAD, &(Segment::AccessedStorageKeys as usize))); if pred_addr != addr || pred_slot_key != key { - self.access_lists_ptrs.storage.insert( + self.access_lists_ptrs.storage_pointers.insert( (addr, key), u256_to_usize( self.memory @@ -573,12 +592,12 @@ impl GenerationState { let (_, &ptr) = self .access_lists_ptrs - .storage + .storage_pointers .range(..(addr, key)) .next_back() .unwrap_or((&DUMMYHEAD, &(Segment::AccessedStorageKeys as usize))); self.access_lists_ptrs - .storage + .storage_pointers .remove(&(addr, key)) .ok_or(ProgramError::ProverInputError(InvalidInput))?; @@ -596,14 +615,14 @@ impl GenerationState { fn run_next_insert_account(&mut self, input_fn: &ProverInputFn) -> Result { let addr = stack_peek(self, 0)?; let (&pred_addr, &pred_ptr) = self - .state_ptrs - .accounts + .state_pointers + .accounts_pointers .range(..=addr) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); if pred_addr != addr && input_fn.0[1].as_str() == "insert_account" { - self.state_ptrs.accounts.insert( + self.state_pointers.accounts_pointers.insert( addr, u256_to_usize( self.memory @@ -648,13 +667,13 @@ impl GenerationState { let key = stack_peek(self, 1)?; let (&(pred_addr, pred_slot_key), &pred_ptr) = self - .state_ptrs - .storage + .state_pointers + .storage_pointers .range(..=(addr, key)) .next_back() .unwrap_or((&DUMMYHEAD, &(Segment::StorageLinkedList as usize))); if (pred_addr != addr || pred_slot_key != key) && input_fn.0[1] == "insert_slot" { - self.state_ptrs.storage.insert( + self.state_pointers.storage_pointers.insert( (addr, key), u256_to_usize( self.memory @@ -675,13 +694,13 @@ impl GenerationState { let addr = stack_peek(self, 0)?; let (_, &ptr) = self - .state_ptrs - .accounts + .state_pointers + .accounts_pointers .range(..addr) .next_back() .unwrap_or((&U256::MAX, &(Segment::AccountsLinkedList as usize))); - self.state_ptrs - .accounts + self.state_pointers + .accounts_pointers .remove(&addr) .ok_or(ProgramError::ProverInputError(InvalidInput))?; @@ -724,13 +743,13 @@ impl GenerationState { let key = stack_peek(self, 1)?; let (_, &ptr) = self - .state_ptrs - .storage + .state_pointers + .storage_pointers .range(..(addr, key)) .next_back() .unwrap_or((&DUMMYHEAD, &(Segment::StorageLinkedList as usize))); - self.state_ptrs - .storage + self.state_pointers + .storage_pointers .remove(&(addr, key)) .ok_or(ProgramError::ProverInputError(InvalidInput))?; @@ -748,8 +767,8 @@ impl GenerationState { let addr = stack_peek(self, 0)?; let (_, &pred_ptr) = self - .state_ptrs - .storage + .state_pointers + .storage_pointers .range(..(addr, U256::zero())) .next_back() .unwrap_or((&DUMMYHEAD, &(Segment::StorageLinkedList as usize))); diff --git a/evm_arithmetization/src/generation/segments.rs b/evm_arithmetization/src/generation/segments.rs index a3ac4057b..2f58c02ec 100644 --- a/evm_arithmetization/src/generation/segments.rs +++ b/evm_arithmetization/src/generation/segments.rs @@ -45,51 +45,6 @@ impl GenerationSegmentData { /// Builds a new `GenerationSegmentData`. #[allow(clippy::unwrap_or_default)] -#[cfg(feature = "eth_mainnet")] -fn build_segment_data( - segment_index: usize, - registers_before: Option, - registers_after: Option, - memory: Option, - interpreter: &Interpreter, -) -> GenerationSegmentData { - GenerationSegmentData { - segment_index, - registers_before: registers_before.unwrap_or(RegistersState::new()), - registers_after: registers_after.unwrap_or(RegistersState::new()), - memory: memory.unwrap_or(MemoryState { - preinitialized_segments: interpreter - .generation_state - .memory - .preinitialized_segments - .clone(), - ..Default::default() - }), - max_cpu_len_log: interpreter.get_max_cpu_len_log(), - extra_data: ExtraSegmentData { - bignum_modmul_result_limbs: interpreter - .generation_state - .bignum_modmul_result_limbs - .clone(), - rlp_prover_inputs: interpreter.generation_state.rlp_prover_inputs.clone(), - withdrawal_prover_inputs: interpreter - .generation_state - .withdrawal_prover_inputs - .clone(), - ger_prover_inputs: interpreter.generation_state.ger_prover_inputs.clone(), - trie_root_ptrs: interpreter.generation_state.trie_root_ptrs.clone(), - jumpdest_table: interpreter.generation_state.jumpdest_table.clone(), - next_txn_index: interpreter.generation_state.next_txn_index, - access_lists_ptrs: interpreter.generation_state.access_lists_ptrs.clone(), - state_ptrs: interpreter.generation_state.state_ptrs.clone(), - }, - opcode_counts: interpreter.opcode_count.clone(), - } -} - -/// Builds a new `GenerationSegmentData`. -#[allow(clippy::unwrap_or_default)] -#[cfg(feature = "cdk_erigon")] fn build_segment_data( segment_index: usize, registers_before: Option, @@ -125,6 +80,7 @@ fn build_segment_data( jumpdest_table: interpreter.generation_state.jumpdest_table.clone(), next_txn_index: interpreter.generation_state.next_txn_index, state_ptrs: interpreter.generation_state.state_pointers.clone(), + access_lists_ptrs: interpreter.generation_state.access_lists_ptrs.clone(), }, opcode_counts: interpreter.opcode_count.clone(), } @@ -250,6 +206,10 @@ impl Iterator for SegmentDataIterator { Some(boxed) => { let (data, next_data) = *boxed; self.partial_next_data = next_data; + println!( + "smt in interpreter {:?}", + self.interpreter.generation_state.state_pointers.state + ); Some(Ok((self.interpreter.generation_state.inputs.clone(), data))) } // The payload was fully consumed. diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index ca2d3d27a..48e8c92b1 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -201,12 +201,12 @@ pub(crate) trait State { let mut running = true; let mut final_clock = 0; - let mem = self - .get_generation_state() - .memory - .get_preinit_memory(Segment::AccountsLinkedList); #[cfg(test)] { + let mem = self + .get_generation_state() + .memory + .get_preinit_memory(Segment::AccountsLinkedList); use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; log::debug!( "initial state linked list = {:?}", @@ -218,6 +218,12 @@ pub(crate) trait State { let registers = self.get_registers(); let pc = registers.program_counter; + if pc == KERNEL.global_labels["check_final_state_trie"] { + log::debug!( + "final state linked list {:?}", + self.get_generation_state().state_pointers + ); + } let halt_final = registers.is_kernel && halt_offsets.contains(&pc); if running && (self.at_halt() || self.at_end_segment(cycle_limit)) { running = false; @@ -404,7 +410,6 @@ pub struct GenerationState { /// Provides quick access to pointers that reference the location /// of either an account or a slot in the respective linked list. - #[cfg(feature = "eth_mainnet")] pub(crate) state_pointers: StateLinkedListsPtrs, } @@ -421,6 +426,7 @@ impl GenerationState { load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); let receipt_root_ptr = load_receipts_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); + println!("trie data length after init {}", trie_data.len()); self.memory.insert_preinitialized_segment( Segment::TrieData, crate::witness::memory::MemorySegmentState { content: trie_data }, @@ -441,6 +447,7 @@ impl GenerationState { trie_inputs, ) .expect("Invalid MPT data for preinitialization"); + println!("trie data len after linked lists {}", trie_data.len()); self.memory.insert_preinitialized_segment( Segment::AccountsLinkedList, crate::witness::memory::MemorySegmentState { @@ -695,35 +702,6 @@ impl GenerationState { } } - #[cfg(feature = "eth_mainnet")] - pub(crate) fn set_segment_data(&mut self, segment_data: &GenerationSegmentData) { - self.bignum_modmul_result_limbs - .clone_from(&segment_data.extra_data.bignum_modmul_result_limbs); - self.rlp_prover_inputs - .clone_from(&segment_data.extra_data.rlp_prover_inputs); - self.withdrawal_prover_inputs - .clone_from(&segment_data.extra_data.withdrawal_prover_inputs); - self.ger_prover_inputs - .clone_from(&segment_data.extra_data.ger_prover_inputs); - self.trie_root_ptrs - .clone_from(&segment_data.extra_data.trie_root_ptrs); - self.jumpdest_table - .clone_from(&segment_data.extra_data.jumpdest_table); - self.state_pointers - .clone_from(&segment_data.extra_data.state_ptrs); - self.access_lists_ptrs - .clone_from(&segment_data.extra_data.access_lists_ptrs); - self.next_txn_index = segment_data.extra_data.next_txn_index; - self.registers = RegistersState { - program_counter: self.registers.program_counter, - is_kernel: self.registers.is_kernel, - is_stack_top_read: false, - check_overflow: false, - ..segment_data.registers_before - }; - } - - #[cfg(feature = "cdk_erigon")] pub(crate) fn set_segment_data(&mut self, segment_data: &GenerationSegmentData) { self.bignum_modmul_result_limbs .clone_from(&segment_data.extra_data.bignum_modmul_result_limbs); diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index f581f8b25..5352e530f 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -13,6 +13,7 @@ use mpt_trie::{ use plonky2::{ field::goldilocks_field::GoldilocksField, util::serialization::gate_serialization::default, }; +#[cfg(feature = "cdk_erigon")] use smt_trie::smt::Smt; pub use crate::cpu::kernel::cancun_constants::*; @@ -169,6 +170,14 @@ pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp } } +#[cfg(feature = "eth_mainnet")] +pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { + AccountRlp { + storage_root: storage_trie.hash(), + ..Default::default() + } +} + fn empty_payload() -> Result { // Set up default block metadata let block_metadata = BlockMetadata { From 8bc4b1226cad71ca17008102a20a6b53505c6e6d Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 29 Oct 2024 10:36:59 +0100 Subject: [PATCH 33/60] Fix more tests --- .../src/cpu/kernel/asm/account_code.asm | 10 +++++----- .../src/cpu/kernel/asm/core/precompiles/main.asm | 3 ++- .../src/cpu/kernel/asm/journal/account_destroyed.asm | 2 +- .../kernel/asm/linked_list/type2/state_linked_list.asm | 2 +- .../cpu/kernel/asm/transactions/common_decoding.asm | 1 + smt_trie/src/code.rs | 6 +++--- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 5e3b5ce77..1b246e9ad 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -216,17 +216,17 @@ load_code_padded_ctd: // Pad with 0s until the length is a multiple of 56 PUSH 56 DUP4 %increment - global debug_len_p_one: - // stack: curr_len, 56, padding_addr, addr, len, retdest - PUSH 56 SWAP1 SUB - // stack: curr_len - 56, 56, padding_addr, addr, len, retdest MOD - global debug_to_padd: +global debug_len_mod_56: + + // curr_len mod 56, padding_addr, addr, len, retdest + PUSH 56 SUB // stack: padding_len, padding_addr, addr, len, retdest SWAP3 DUP4 // stack: padding_len, len, padding_addr, addr, padding_len, retdest ADD // stack: last_byte_offset, padding_addr, addr, padding_len, retdest + global debug_padding_len: %stack (last_byte_offset, padding_addr, addr, padding_len) -> (padding_addr, padding_len, after_padding, addr, last_byte_offset) %jump(memset) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm b/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm index 1f1aa5af5..4b2b31df4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/precompiles/main.asm @@ -25,7 +25,8 @@ global handle_precompiles: } #[cfg(not(feature = eth_mainnet))] { - %eq_const(@BLAKE2_F) %jumpi(precompile_blake2_f) + DUP1 %eq_const(@BLAKE2_F) %jumpi(precompile_blake2_f) + POP } // TODO: Add support of EIP-7712 for Polygon Pos, https://github.com/0xPolygonZero/zk_evm/issues/265 // stack: retdest 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 2f6b1febc..15654ad29 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm @@ -45,7 +45,7 @@ revert_account_destroyed_contd: SWAP1 // Remove `prev_balance` from `target`'s balance. // stack: target, address, prev_balance, retdest - %key_balance DUP1 %search_key %mload_trie_data + %key_balance DUP1 %search_key // stack: target_balance, target_balance_key, address, prev_balance, retdest %stack (target_balance, target_balance_key, address, prev_balance) -> (target_balance, prev_balance, target_balance_key, address, prev_balance) // stack: target_balance, prev_balance, target_balance_key, address, prev_balance, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index f9e78c980..993e771b7 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -458,7 +458,7 @@ not_found: %macro read_slot_from_addr // stack: address, slot - %addr_to_state_key + // %addr_to_state_key %key_storage %stack (storage_key) -> (storage_key, %%after) // stack: storage_key, %%after 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 41848c4cc..1a5140760 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm @@ -231,6 +231,7 @@ insert_accessed_storage_keys_with_original_value: after_read: %stack (value, addr, key, retdest) -> (addr, key, value, retdest) %insert_accessed_storage_keys +global debug_si_por_aca: // stack: cold_access, value_ptr, value, retdest SWAP2 // stack: value, value_ptr, cold_access, retdest diff --git a/smt_trie/src/code.rs b/smt_trie/src/code.rs index bfed04a7d..1cc0e4bcb 100644 --- a/smt_trie/src/code.rs +++ b/smt_trie/src/code.rs @@ -10,8 +10,8 @@ use crate::utils::hashout2u; pub fn hash_contract_bytecode(mut code: Vec) -> HashOut { poseidon_pad_byte_vec(&mut code); - println!("code bytes = {:?}", code); - println!("hash = {:?}", hashout2u(poseidon_hash_padded_byte_vec(code.clone()))); + // println!("code bytes = {:?}", code); + // println!("hash = {:?}", hashout2u(poseidon_hash_padded_byte_vec(code.clone()))); poseidon_hash_padded_byte_vec(code) } @@ -39,7 +39,7 @@ pub fn poseidon_hash_padded_byte_vec(bytes: Vec) -> HashOut { pub fn poseidon_pad_byte_vec(bytes: &mut Vec) { bytes.push(0x01); - println!("code len = {:?}", bytes.len()); + // println!("code len = {:?}", bytes.len()); while bytes.len() % 56 != 0 { bytes.push(0x00); } From 013560d32e81c6f38e6627099fd90e0ec4de31ee Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 29 Oct 2024 12:41:35 +0100 Subject: [PATCH 34/60] Keep changes --- evm_arithmetization/src/cpu/kernel/asm/main.asm | 6 +++--- evm_arithmetization/src/generation/state.rs | 6 ------ smt_trie/src/smt_test.rs | 14 ++++++++------ trace_decoder/src/core.rs | 1 + 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 5f0252b82..57dc8368c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -135,9 +135,9 @@ global start_txns: #[cfg(feature = cdk_erigon)] { // If txn_idx == 0, perform pre-state execution for CDK erigon. - // %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) - // ISZERO - // %jumpi(pre_block_execution) + %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE) + ISZERO + %jumpi(pre_block_execution) } // stack: init_gas_used, txn_counter, num_nibbles, txn_nb diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 48e8c92b1..e3a02d990 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -218,12 +218,6 @@ pub(crate) trait State { let registers = self.get_registers(); let pc = registers.program_counter; - if pc == KERNEL.global_labels["check_final_state_trie"] { - log::debug!( - "final state linked list {:?}", - self.get_generation_state().state_pointers - ); - } let halt_final = registers.is_kernel && halt_offsets.contains(&pc); if running && (self.at_halt() || self.at_end_segment(cycle_limit)) { running = false; diff --git a/smt_trie/src/smt_test.rs b/smt_trie/src/smt_test.rs index 57186aac3..d862b39a6 100644 --- a/smt_trie/src/smt_test.rs +++ b/smt_trie/src/smt_test.rs @@ -391,13 +391,15 @@ fn test_serialize_and_prune() { .collect::>() }; - let pruned_ser = smt.serialize_and_prune(subset); - assert_eq!(hash_serialize(&pruned_ser), smt.root); - assert!(pruned_ser.len() <= ser.len()); + let mut v = vec![U256::zero(), U256::zero()]; + smt.serialize_and_prune(subset, &mut v, 0); + assert_eq!(hash_serialize(&v), smt.root); + assert!(v.len() <= ser.len()); - let trivial_ser = smt.serialize_and_prune::>(vec![]); + let mut v = vec![U256::zero(), U256::zero()]; + smt.serialize_and_prune::>(vec![], &mut v, 0); assert_eq!( - trivial_ser, + v, vec![ U256::zero(), U256::zero(), @@ -405,5 +407,5 @@ fn test_serialize_and_prune() { hashout2u(smt.root) ] ); - assert_eq!(hash_serialize(&trivial_ser), smt.root); + assert_eq!(hash_serialize(&v), smt.root); } diff --git a/trace_decoder/src/core.rs b/trace_decoder/src/core.rs index 46495030f..edff6f937 100644 --- a/trace_decoder/src/core.rs +++ b/trace_decoder/src/core.rs @@ -152,6 +152,7 @@ pub fn entrypoint( }, transactions_trie: transaction.into(), receipts_trie: receipt.into(), + #[cfg(feature = "eth_mainnet")] storage_tries: storage.into_iter().map(|(k, v)| (k, v.into())).collect(), }, trie_roots_after: after, From f77e018e0db2190454c73927bc012f9c6480f7e0 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 30 Oct 2024 10:44:39 +0100 Subject: [PATCH 35/60] Last fixes --- evm_arithmetization/src/cpu/kernel/asm/core/call.asm | 1 + evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm | 1 + 2 files changed, 2 insertions(+) diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/call.asm b/evm_arithmetization/src/cpu/kernel/asm/core/call.asm index ab8b67c4e..d8ff6dd36 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/call.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/call.asm @@ -25,6 +25,7 @@ global sys_call: DUP1 %insert_accessed_addresses %call_charge_gas(1, 1) +global debug_after_charge_gas: %check_depth %checkpoint // Checkpoint diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm b/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm index c70de697b..9a2262fc9 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm @@ -53,6 +53,7 @@ after_new_cost: %charge_gas // Compute C_callgas +global debug_por_aca: %stack (kexit_info, Cgascap, address, gas, value) -> (Cgascap, address, gas, kexit_info, value) DUP5 ISZERO %not_bit From 44009a8383c130725cd36deb1702c91bc7d3ac5a Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Wed, 30 Oct 2024 11:23:06 +0100 Subject: [PATCH 36/60] Add AccountRlp trait --- .../benches/fibonacci_25m_gas.rs | 132 +++++++++++++----- .../src/cpu/kernel/tests/account_code.rs | 31 ++-- .../src/cpu/kernel/tests/balance.rs | 9 +- .../src/cpu/kernel/tests/mpt/mod.rs | 32 +++-- evm_arithmetization/src/generation/mpt.rs | 101 ++++++++++++-- evm_arithmetization/tests/erc20_type2.rs | 22 +-- trace_decoder/src/tries.rs | 10 +- trace_decoder/src/world.rs | 4 +- 8 files changed, 245 insertions(+), 96 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 3a8b60c38..796d47da4 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -4,6 +4,7 @@ //! Total number of user instructions: 7_136_858. //! Total number of loops: 2_378_952. +use std::any::Any; use std::collections::HashMap; use std::str::FromStr; @@ -14,7 +15,10 @@ use ethereum_types::{Address, H256, U256}; use ethereum_types::{BigEndianHash, H160}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; +use evm_arithmetization::generation::mpt::{ + get_h256_from_code_hash, get_u256_from_code_hash, AccountRlp, CodeHashType, LegacyReceiptRlp, + MptAccountRlp, +}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::simulate_execution; @@ -90,38 +94,58 @@ fn prepare_setup() -> anyhow::Result> { ]; let code_hash = keccak(code); #[cfg(feature = "cdk_erigon")] - let code_hash = hash_bytecode_u256(code.to_vec()); + let code_hash = CodeHashType::Uint(hash_bytecode_u256(code.to_vec())); let empty_trie_root = HashedPartialTrie::from(Node::Empty).hash(); #[cfg(feature = "eth_mainnet")] - let sender_account_before = AccountRlp { + let sender_account_before = Box::new(MptAccountRlp { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, storage_root: empty_trie_root, code_hash: keccak(vec![]), - }; + }); #[cfg(feature = "eth_mainnet")] - let to_account_before = AccountRlp { + let to_account_before = Box::new(MptAccountRlp { nonce: 1.into(), balance: 0.into(), storage_root: empty_trie_root, code_hash, - }; + }); #[cfg(feature = "cdk_erigon")] - let sender_account_before = AccountRlp { - nonce: 169.into(), - balance: U256::from_dec_str("999999999998417410153631615")?, - code_hash: hash_bytecode_u256(vec![]), - code_length: 0.into(), + let sender_account_before: Box = if cfg!(feature = "cdk_erigon") { + Box::new(SmtAccountRlp { + nonce: 169.into(), + balance: U256::from_dec_str("999999999998417410153631615")?, + code_hash: hash_bytecode_u256(vec![]), + code_length: 0.into(), + }) + } else { + Box::new(MptAccountRlp { + nonce: 169.into(), + balance: U256::from_dec_str("999999999998417410153631615")?, + storage_root: empty_trie_root, + code_hash: keccak(vec![]), + }) }; #[cfg(feature = "cdk_erigon")] - let to_account_before = AccountRlp { - nonce: 1.into(), - balance: 0.into(), - code_hash, - code_length: code.len().into(), + let to_account_before: Box = if cfg!(feature = "cdk_erigon") { + Box::new(SmtAccountRlp { + nonce: 1.into(), + balance: 0.into(), + code_hash: get_u256_from_code_hash(code_hash.clone()) + .expect("In cdk_erigon, the code_hash is a U256"), + code_length: code.len().into(), + }) + } else { + Box::new(MptAccountRlp { + nonce: 1.into(), + balance: 0.into(), + storage_root: empty_trie_root, + code_hash: get_h256_from_code_hash(code_hash.clone()) + .expect("In eth_mainnet, the code_hash is a H256"), + }) }; #[cfg(feature = "eth_mainnet")] @@ -143,19 +167,28 @@ fn prepare_setup() -> anyhow::Result> { set_account( &mut smt_before, H160(sender), - &sender_account_before, + sender_account_before + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT."), &HashMap::new(), ); set_account( &mut smt_before, H160(to), - &to_account_before, + to_account_before + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT."), &HashMap::new(), ); - let sender_account_after = AccountRlp { - nonce: sender_account_before.nonce + 1, - balance: sender_account_before.balance, - ..sender_account_before + let sender_account_after = SmtAccountRlp { + nonce: sender_account_before.get_nonce() + 1, + balance: sender_account_before.get_balance(), + ..*sender_account_before + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT.") }; } @@ -198,15 +231,36 @@ fn prepare_setup() -> anyhow::Result> { #[cfg(feature = "cdk_erigon")] { contract_code.insert(hash_bytecode_u256(vec![]), vec![]); - contract_code.insert(code_hash, code.to_vec()); + contract_code.insert( + get_u256_from_code_hash(code_hash).expect("In cdk_erigon, the code_hash is a U256"), + code.to_vec(), + ); } - let sender_account_after = AccountRlp { - balance: sender_account_before.balance - value - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before.nonce + 1, - ..sender_account_before + let sender_account_after: Box = if cfg!(feature = "cdk_erigon") { + Box::new(SmtAccountRlp { + balance: sender_account_before.get_balance() + - value + - gas_used * block_metadata.block_base_fee, + nonce: sender_account_before.get_nonce() + 1, + ..*sender_account_before + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT.") + }) + } else { + Box::new(MptAccountRlp { + balance: sender_account_before.get_balance() + - value + - gas_used * block_metadata.block_base_fee, + nonce: sender_account_before.get_nonce() + 1, + ..*sender_account_before + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT.") + }) }; - let to_account_after = to_account_before; + let to_account_after = &to_account_before; #[cfg(feature = "eth_mainnet")] let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); @@ -235,13 +289,19 @@ fn prepare_setup() -> anyhow::Result> { set_account::( &mut expected_smt_after, H160(sender), - &sender_account_after, + sender_account_after + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT."), &HashMap::new(), ); set_account( &mut expected_smt_after, H160(to), - &to_account_after, + to_account_before + .as_any() + .downcast_ref::() + .expect("The sender account is an SMT."), &HashMap::new(), ); } @@ -302,23 +362,25 @@ fn init_logger() { criterion_group!(benches, criterion_benchmark); criterion_main!(benches); +use evm_arithmetization::generation::mpt::SmtAccountRlp; + #[cfg(feature = "cdk_erigon")] fn set_account( smt: &mut Smt, addr: Address, - account: &AccountRlp, + account: &SmtAccountRlp, storage: &HashMap, ) { let key = key_balance(addr); log::debug!( "setting {:?} balance to {:?}, the key is {:?}", addr, - account.balance, + account.get_balance(), U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) ); - smt.set(key_balance(addr), account.balance); - smt.set(key_nonce(addr), account.nonce); - smt.set(key_code(addr), account.code_hash); + smt.set(key_balance(addr), account.get_balance()); + smt.set(key_nonce(addr), account.get_nonce()); + smt.set(key_code(addr), account.get_code_hash_u256()); let key = key_code_length(addr); log::debug!( "setting {:?} code length, the key is {:?}", diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 094dcd287..93ec2c6f1 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -18,9 +18,9 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; -use crate::generation::mpt::AccountRlp; #[cfg(feature = "eth_mainnet")] use crate::generation::mpt::{load_linked_lists_and_txn_and_receipt_mpts, load_state_mpt}; +use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -153,7 +153,7 @@ pub(crate) fn initialize_mpts( pub(crate) fn prepare_interpreter( interpreter: &mut Interpreter, address: Address, - account: &AccountRlp, + account: Box, ) -> Result<()> { let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; @@ -184,16 +184,13 @@ pub(crate) fn prepare_interpreter( trie_data.push(Some(0.into())); } let value_ptr = trie_data.len(); - trie_data.push(Some(account.nonce)); - trie_data.push(Some(account.balance)); + trie_data.push(Some(account.get_nonce())); + trie_data.push(Some(account.get_balance())); // In memory, storage_root gets interpreted as a pointer to a storage trie, // so we have to ensure the pointer is valid. It's easiest to set it to 0, // which works as an empty node, since trie_data[0] = 0 = MPT_TYPE_EMPTY. trie_data.push(Some(H256::zero().into_uint())); - #[cfg(feature = "eth_mainnet")] - trie_data.push(Some(account.code_hash.into_uint())); - #[cfg(feature = "cdk_erigon")] - trie_data.push(Some(account.code_hash)); + trie_data.push(Some(account.get_code_hash_u256())); let trie_data_len = trie_data.len().into(); interpreter.set_global_metadata_field(GlobalMetadata::TrieDataSize, trie_data_len); interpreter @@ -241,7 +238,7 @@ pub(crate) fn prepare_interpreter( interpreter.set_global_metadata_field(GlobalMetadata::StateTrieRoot, state_root); // Now, execute `mpt_hash_state_trie`. - state_trie.insert(k, rlp::encode(account).to_vec())?; + state_trie.insert(k, account.rlp_encode().to_vec())?; let expected_state_trie_hash = state_trie.hash(); interpreter.set_global_metadata_field( GlobalMetadata::StateTrieRootDigestAfter, @@ -272,8 +269,8 @@ pub(crate) fn prepare_interpreter( // Test account with a given code hash. #[cfg(feature = "eth_mainnet")] -fn test_account(code: &[u8]) -> AccountRlp { - AccountRlp { +fn test_account(code: &[u8]) -> MptAccountRlp { + MptAccountRlp { nonce: U256::from(1111), balance: U256::from(2222), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -283,8 +280,8 @@ fn test_account(code: &[u8]) -> AccountRlp { // Test account with a given code hash. #[cfg(feature = "cdk_erigon")] -fn test_account(code: &[u8]) -> AccountRlp { - AccountRlp { +fn test_account(code: &[u8]) -> SmtAccountRlp { + SmtAccountRlp { nonce: U256::from(1111), balance: U256::from(2222), code_hash: hash_bytecode_u256(code.to_vec()), @@ -301,12 +298,12 @@ fn random_code() -> Vec { #[test] fn test_extcodesize() -> Result<()> { let code = random_code(); - let account = test_account(&code); + let account = Box::new(test_account(&code)); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); let address: Address = thread_rng().gen(); // Prepare the interpreter by inserting the account in the state trie. - prepare_interpreter(&mut interpreter, address, &account)?; + prepare_interpreter(&mut interpreter, address, account)?; let extcodesize = KERNEL.global_labels["extcodesize"]; @@ -345,12 +342,12 @@ fn test_extcodesize() -> Result<()> { #[test] fn test_extcodecopy() -> Result<()> { let code = random_code(); - let account = test_account(&code); + let account = Box::new(test_account(&code)); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); let address: Address = thread_rng().gen(); // Prepare the interpreter by inserting the account in the state trie. - prepare_interpreter(&mut interpreter, address, &account)?; + prepare_interpreter(&mut interpreter, address, account)?; let context = interpreter.context(); interpreter.generation_state.memory.contexts[context].segments diff --git a/evm_arithmetization/src/cpu/kernel/tests/balance.rs b/evm_arithmetization/src/cpu/kernel/tests/balance.rs index dc8eab845..2f2a84b0d 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/balance.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/balance.rs @@ -8,6 +8,7 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::prepare_interpreter; use crate::generation::mpt::AccountRlp; +use crate::generation::mpt::SmtAccountRlp; use crate::Node; // Test account with a given code hash. @@ -23,10 +24,10 @@ fn test_account(balance: U256) -> AccountRlp { // Test account with a given code hash. #[cfg(feature = "cdk_erigon")] -fn test_account(balance: U256) -> AccountRlp { +fn test_account(balance: U256) -> SmtAccountRlp { use smt_trie::code::hash_bytecode_u256; - AccountRlp { + SmtAccountRlp { nonce: U256::from(1111), balance, code_hash: hash_bytecode_u256(vec![0x01, 0x00]), @@ -38,12 +39,12 @@ fn test_account(balance: U256) -> AccountRlp { fn test_balance() -> Result<()> { let mut rng = thread_rng(); let balance = U256(rng.gen()); - let account = test_account(balance); + let account = Box::new(test_account(balance)); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); let address: Address = rng.gen(); // Prepare the interpreter by inserting the account in the state trie. - prepare_interpreter(&mut interpreter, address, &account)?; + prepare_interpreter(&mut interpreter, address, account)?; // Test `balance` interpreter.generation_state.registers.program_counter = KERNEL.global_labels["balance"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 1207eab84..1ef94bbbb 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -3,7 +3,7 @@ use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::HashedPartialTrie; use mpt_trie::partial_trie::PartialTrie; -use crate::generation::mpt::AccountRlp; +use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; use crate::Node; #[cfg(feature = "eth_mainnet")] @@ -56,36 +56,36 @@ pub(crate) fn test_account_1_empty_storage() -> AccountRlp { } #[cfg(feature = "cdk_erigon")] -pub(crate) fn test_account_1() -> AccountRlp { - AccountRlp { +pub(crate) fn test_account_1() -> Box { + Box::new(SmtAccountRlp { nonce: U256::from(1111), balance: U256::from(2222), code_hash: U256::from(4444), code_length: 0.into(), - } + }) } #[cfg(feature = "cdk_erigon")] -pub(crate) fn test_account_1_empty_storage() -> AccountRlp { - AccountRlp { +pub(crate) fn test_account_1_empty_storage() -> Box { + Box::new(SmtAccountRlp { nonce: U256::from(1111), balance: U256::from(2222), code_hash: U256::from(4444), code_length: 0.into(), - } + }) } pub(crate) fn test_account_1_rlp() -> Vec { - rlp::encode(&test_account_1()).to_vec() + test_account_1().rlp_encode().to_vec() } pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { - rlp::encode(&test_account_1_empty_storage()).to_vec() + test_account_1_empty_storage().rlp_encode().to_vec() } #[cfg(feature = "eth_mainnet")] -pub(crate) fn test_account_2() -> AccountRlp { - AccountRlp { +pub(crate) fn test_account_2() -> Box { + MptAccountRlp { nonce: U256::from(5555), balance: U256::from(6666), storage_root: H256::from_uint(&U256::from(7777)), @@ -94,17 +94,19 @@ pub(crate) fn test_account_2() -> AccountRlp { } #[cfg(feature = "cdk_erigon")] -pub(crate) fn test_account_2() -> AccountRlp { - AccountRlp { +pub(crate) fn test_account_2() -> Box { + use crate::generation::mpt::SmtAccountRlp; + + Box::new(SmtAccountRlp { nonce: U256::from(5555), balance: U256::from(6666), code_hash: U256::from(8888), code_length: 0.into(), - } + }) } pub(crate) fn test_account_2_rlp() -> Vec { - rlp::encode(&test_account_2()).to_vec() + test_account_2().rlp_encode().to_vec() } /// A `PartialTrie` where an extension node leads to a leaf node containing an diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 133ab35bf..8a66d826c 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -1,7 +1,8 @@ use core::ops::Deref; +use std::any::Any; use std::collections::{BTreeMap, HashMap}; -use bytes::Bytes; +use bytes::{Bytes, BytesMut}; use ethereum_types::{Address, BigEndianHash, H256, U256}; use keccak_hash::keccak; use mpt_trie::nibbles::{Nibbles, NibblesIntern}; @@ -22,24 +23,107 @@ use crate::util::h2u; use crate::witness::errors::{ProgramError, ProverInputError}; use crate::Node; +#[derive(Clone)] +pub enum CodeHashType { + Hash(H256), + Uint(U256), +} + +pub fn get_h256_from_code_hash(code_hash: CodeHashType) -> Option { + match code_hash { + CodeHashType::Hash(h) => Some(h), + _ => None, + } +} + +pub fn get_u256_from_code_hash(code_hash: CodeHashType) -> Option { + match code_hash { + CodeHashType::Uint(u) => Some(u), + _ => None, + } +} + #[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[cfg(feature = "eth_mainnet")] -pub struct AccountRlp { +pub struct MptAccountRlp { pub nonce: U256, pub balance: U256, pub storage_root: H256, pub code_hash: H256, } +impl AccountRlp for MptAccountRlp { + fn as_any(&self) -> &dyn Any { + self + } + fn get_nonce(&self) -> U256 { + self.nonce + } + fn get_balance(&self) -> U256 { + self.balance + } + fn get_storage_root(&self) -> H256 { + self.storage_root + } + fn get_code_length(&self) -> U256 { + panic!("No code length in an MPT's account.") + } + fn get_code_hash(&self) -> CodeHashType { + CodeHashType::Hash(self.code_hash) + } + fn get_code_hash_u256(&self) -> U256 { + self.code_hash.into_uint() + } + fn rlp_encode(&self) -> BytesMut { + rlp::encode(self) + } +} + #[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[cfg(feature = "cdk_erigon")] -pub struct AccountRlp { +pub struct SmtAccountRlp { pub nonce: U256, pub balance: U256, pub code_length: U256, pub code_hash: U256, } +impl AccountRlp for SmtAccountRlp { + fn as_any(&self) -> &dyn Any { + self + } + fn get_nonce(&self) -> U256 { + self.nonce + } + fn get_balance(&self) -> U256 { + self.balance + } + fn get_storage_root(&self) -> H256 { + panic!("No storage root in an SMT's account.") + } + fn get_code_length(&self) -> U256 { + self.code_length + } + fn get_code_hash(&self) -> CodeHashType { + CodeHashType::Uint(self.code_hash) + } + fn get_code_hash_u256(&self) -> U256 { + self.code_hash + } + fn rlp_encode(&self) -> BytesMut { + rlp::encode(self) + } +} + +pub trait AccountRlp: Any { + fn get_nonce(&self) -> U256; + fn get_balance(&self) -> U256; + fn get_storage_root(&self) -> H256; + fn get_code_length(&self) -> U256; + fn get_code_hash(&self) -> CodeHashType; + fn get_code_hash_u256(&self) -> U256; + fn rlp_encode(&self) -> BytesMut; + fn as_any(&self) -> &dyn Any; +} + #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct TrieRootPtrs { pub state_root_ptr: Option, @@ -47,8 +131,7 @@ pub struct TrieRootPtrs { pub receipt_root_ptr: usize, } -impl Default for AccountRlp { - #[cfg(feature = "eth_mainnet")] +impl Default for MptAccountRlp { fn default() -> Self { Self { nonce: U256::zero(), @@ -57,7 +140,9 @@ impl Default for AccountRlp { code_hash: keccak([]), } } - #[cfg(feature = "cdk_erigon")] +} + +impl Default for SmtAccountRlp { fn default() -> Self { use smt_trie::code::hash_bytecode_u256; diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index baf5f9039..abfea9930 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use std::time::Duration; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, SmtAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -122,7 +122,7 @@ fn test_erc20() -> anyhow::Result<()> { let expected_smt_after: Smt = { let mut smt = Smt::default(); let sender_account = sender_account(); - let sender_account_after = AccountRlp { + let sender_account_after = SmtAccountRlp { nonce: sender_account.nonce + 1, balance: sender_account.balance - gas_used * 0xa, ..sender_account @@ -290,10 +290,10 @@ fn scalable_storage_after(block: &BlockMetadata, state_root_before: U256) -> Has storage } -fn giver_account() -> AccountRlp { +fn giver_account() -> SmtAccountRlp { let code = giver_bytecode(); let len = code.len(); - AccountRlp { + SmtAccountRlp { nonce: 1.into(), balance: 0.into(), code_hash: hash_bytecode_u256(code), @@ -301,10 +301,10 @@ fn giver_account() -> AccountRlp { } } -fn token_account() -> AccountRlp { +fn token_account() -> SmtAccountRlp { let code = token_bytecode(); let len = code.len(); - AccountRlp { + SmtAccountRlp { nonce: 1.into(), balance: 0.into(), code_hash: hash_bytecode_u256(code), @@ -312,16 +312,16 @@ fn token_account() -> AccountRlp { } } -fn sender_account() -> AccountRlp { - AccountRlp { +fn sender_account() -> SmtAccountRlp { + SmtAccountRlp { nonce: 0.into(), balance: sd2u("10000000000000000000000"), ..Default::default() } } -fn scalable_account() -> AccountRlp { - AccountRlp { +fn scalable_account() -> SmtAccountRlp { + SmtAccountRlp { nonce: 0.into(), balance: 0.into(), ..Default::default() @@ -347,7 +347,7 @@ fn bloom() -> [U256; 8] { fn set_account( smt: &mut Smt, addr: Address, - account: &AccountRlp, + account: &SmtAccountRlp, storage: &HashMap, ) { let key = key_balance(addr); diff --git a/trace_decoder/src/tries.rs b/trace_decoder/src/tries.rs index 7da8d2cfa..df9c072f7 100644 --- a/trace_decoder/src/tries.rs +++ b/trace_decoder/src/tries.rs @@ -7,7 +7,7 @@ use anyhow::ensure; use bitvec::{array::BitArray, slice::BitSlice}; use copyvec::CopyVec; use ethereum_types::{Address, H256, U256}; -use evm_arithmetization::generation::mpt::AccountRlp; +use evm_arithmetization::generation::mpt::{AccountRlp, MptAccountRlp}; use mpt_trie::partial_trie::{HashedPartialTrie, Node, OnOrphanedHashNode, PartialTrie as _}; use u4::{AsNibbles, U4}; @@ -287,7 +287,7 @@ impl Default for StateMpt { } #[track_caller] -fn assert_rlp_account(bytes: impl AsRef<[u8]>) -> AccountRlp { +fn assert_rlp_account(bytes: impl AsRef<[u8]>) -> MptAccountRlp { rlp::decode(bytes.as_ref()).expect("invalid RLP in StateMPT") } @@ -309,13 +309,13 @@ impl StateMpt { pub fn insert_hash(&mut self, key: MptKey, hash: H256) -> anyhow::Result<()> { Ok(self.inner.insert(key.into_nibbles(), hash)?) } - pub fn insert(&mut self, key: H256, account: AccountRlp) -> anyhow::Result<()> { + pub fn insert(&mut self, key: H256, account: MptAccountRlp) -> anyhow::Result<()> { Ok(self.inner.insert( MptKey::from_hash(key).into_nibbles(), rlp::encode(&account).to_vec(), )?) } - pub fn get(&self, key: H256) -> Option { + pub fn get(&self, key: H256) -> Option { self.inner .get(MptKey::from_hash(key).into_nibbles()) .map(assert_rlp_account) @@ -337,7 +337,7 @@ impl StateMpt { self.inner = new; Ok(()) } - pub fn iter(&self) -> impl Iterator + '_ { + pub fn iter(&self) -> impl Iterator + '_ { self.inner.items().filter_map(|(key, rlp)| match rlp { mpt_trie::trie_ops::ValOrHash::Val(vec) => Some(( MptKey::from_nibbles(key).into_hash().expect("bad depth"), diff --git a/trace_decoder/src/world.rs b/trace_decoder/src/world.rs index fa68854e4..20c98b4c5 100644 --- a/trace_decoder/src/world.rs +++ b/trace_decoder/src/world.rs @@ -4,6 +4,7 @@ use alloy_compat::Compat as _; use anyhow::{ensure, Context as _}; use either::Either; use ethereum_types::{Address, BigEndianHash as _, U256}; +use evm_arithmetization::generation::mpt::AccountRlp; use keccak_hash::H256; use crate::tries::{MptKey, SmtKey, StateMpt, StorageTrie}; @@ -111,7 +112,7 @@ impl Type1World { it }); ensure!( - storage.root() == acct.storage_root, + storage.root() == acct.get_storage_root(), "inconsistent initial storage for hashed address {haddr}" ) } @@ -148,6 +149,7 @@ impl Type1World { impl World for Type1World { type SubtriePath = MptKey; + fn contains(&mut self, address: Address) -> anyhow::Result { Ok(self.state.get(keccak_hash::keccak(address)).is_some()) } From e9d0d492c214a800400c260e9459c82dbf6e5a01 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Wed, 30 Oct 2024 15:58:25 +0100 Subject: [PATCH 37/60] Fix regressions --- .../src/cpu/kernel/asm/account_code.asm | 4 +++ .../src/cpu/kernel/interpreter.rs | 4 ++- .../src/generation/prover_input.rs | 28 +++++++++---------- .../src/generation/segments.rs | 8 +++--- evm_arithmetization/src/generation/state.rs | 6 +--- evm_arithmetization/src/lib.rs | 1 + evm_arithmetization/src/witness/operation.rs | 1 + evm_arithmetization/src/witness/transition.rs | 2 ++ 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 23afcc172..7601dde6b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -217,10 +217,14 @@ load_code_padded_ctd: PUSH 56 DUP4 %increment MOD + DUP1 %jumpi(non_zero_padding) + %jump(padd) +non_zero_padding: global debug_len_mod_56: // curr_len mod 56, padding_addr, addr, len, retdest PUSH 56 SUB +padd: // stack: padding_len, padding_addr, addr, len, retdest SWAP3 DUP4 // stack: padding_len, len, padding_addr, addr, padding_len, retdest diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 54cd84316..cb03b2e69 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -398,7 +398,9 @@ impl Interpreter { self.generation_state.memory.set(address, value); } } - MemoryOpKind::Write => self.generation_state.memory.set(address, value), + MemoryOpKind::Write => { + self.generation_state.memory.set(address, value) + } } } diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index a742eb414..bef56e683 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -146,20 +146,20 @@ impl GenerationState { "txn" => Ok(U256::from(self.trie_root_ptrs.txn_root_ptr)), "receipt" => Ok(U256::from(self.trie_root_ptrs.receipt_root_ptr)), "trie_data_size" => { - println!( - "length {}", - self.memory - .preinitialized_segments - .get(&Segment::TrieData) - .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) - .content - .len() - .max( - self.memory.contexts[0].segments[Segment::TrieData.unscale()] - .content - .len(), - ) - ); + // println!( + // "length {}", + // self.memory + // .preinitialized_segments + // .get(&Segment::TrieData) + // .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) + // .content + // .len() + // .max( + // self.memory.contexts[0].segments[Segment::TrieData.unscale()] + // .content + // .len(), + // ) + // ); Ok(self .memory .preinitialized_segments diff --git a/evm_arithmetization/src/generation/segments.rs b/evm_arithmetization/src/generation/segments.rs index 2f58c02ec..f95a1b1fc 100644 --- a/evm_arithmetization/src/generation/segments.rs +++ b/evm_arithmetization/src/generation/segments.rs @@ -206,10 +206,10 @@ impl Iterator for SegmentDataIterator { Some(boxed) => { let (data, next_data) = *boxed; self.partial_next_data = next_data; - println!( - "smt in interpreter {:?}", - self.interpreter.generation_state.state_pointers.state - ); + // println!( + // "smt in interpreter {:?}", + // self.interpreter.generation_state.state_pointers.state + // ); Some(Ok((self.interpreter.generation_state.inputs.clone(), data))) } // The payload was fully consumed. diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 48e8c92b1..c1d085188 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -259,7 +259,6 @@ pub(crate) trait State { return Ok((final_registers, final_mem)); } } - self.transition()?; } } @@ -278,13 +277,11 @@ pub(crate) trait State { ProgramError::StackOverflow => 5, _ => bail!("TODO: figure out what to do with this..."), }; - let checkpoint = self.checkpoint(); let (row, _) = self.base_row(); generate_exception(exc_code, self, row) .map_err(|e| anyhow!("Exception handling failed with error: {:?}", e))?; - self.apply_ops(checkpoint); Ok(()) @@ -305,7 +302,6 @@ pub(crate) trait State { if might_overflow_op(op) { self.get_mut_registers().check_overflow = true; } - Ok(()) } Err(e) => { @@ -426,7 +422,7 @@ impl GenerationState { load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); let receipt_root_ptr = load_receipts_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); - println!("trie data length after init {}", trie_data.len()); + // println!("trie data length after init {}", trie_data.len()); self.memory.insert_preinitialized_segment( Segment::TrieData, crate::witness::memory::MemorySegmentState { content: trie_data }, diff --git a/evm_arithmetization/src/lib.rs b/evm_arithmetization/src/lib.rs index 41b7f093a..754c04ac8 100644 --- a/evm_arithmetization/src/lib.rs +++ b/evm_arithmetization/src/lib.rs @@ -252,6 +252,7 @@ #![allow(clippy::too_many_arguments)] #![allow(clippy::field_reassign_with_default)] #![feature(let_chains)] +#![feature(const_mut_refs)] zk_evm_common::check_chain_features!(); diff --git a/evm_arithmetization/src/witness/operation.rs b/evm_arithmetization/src/witness/operation.rs index 2fd474aec..76813d5a5 100644 --- a/evm_arithmetization/src/witness/operation.rs +++ b/evm_arithmetization/src/witness/operation.rs @@ -888,6 +888,7 @@ pub(crate) fn generate_mload_general>( state.push_memory(log_read); state.push_cpu(row); + Ok(()) } diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 245378496..f3f6c4ec2 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -10,6 +10,7 @@ use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::MAX_CODE_SIZE; use crate::cpu::kernel::opcodes::get_opcode; +#[cfg(test)] use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::stack::{ @@ -324,6 +325,7 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o // Segment::AccountsLinkedList) ); // } + #[cfg(test)] if KERNEL.offset_name(pc) == "smt_hash_state" || KERNEL.offset_name(pc) == "sys_sstore"{ let mem = state .get_generation_state() From 3e7cdb3c14e6b5130671e180e46682e2296c50ac Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Thu, 31 Oct 2024 15:30:14 +0100 Subject: [PATCH 38/60] Start moving world to evm_arithmetization --- Cargo.lock | 16 +++ Cargo.toml | 4 +- evm_arithmetization/Cargo.toml | 12 ++ evm_arithmetization/src/generation/mod.rs | 48 ++++--- evm_arithmetization/src/generation/mpt.rs | 33 +++-- .../src/generation/prover_input.rs | 126 ++++++++++-------- evm_arithmetization/src/generation/state.rs | 37 +++-- evm_arithmetization/src/lib.rs | 1 + evm_arithmetization/src/world/mod.rs | 46 +++++++ .../src/world}/tries.rs | 10 +- .../src/world}/type1.rs | 48 +++---- .../src/world}/type2.rs | 31 ++--- .../src/world}/wire.rs | 0 .../src/world}/world.rs | 42 +++++- trace_decoder/src/lib.rs | 49 +------ 15 files changed, 310 insertions(+), 193 deletions(-) create mode 100644 evm_arithmetization/src/world/mod.rs rename {trace_decoder/src => evm_arithmetization/src/world}/tries.rs (98%) rename {trace_decoder/src => evm_arithmetization/src/world}/type1.rs (93%) rename {trace_decoder/src => evm_arithmetization/src/world}/type2.rs (92%) rename {trace_decoder/src => evm_arithmetization/src/world}/wire.rs (100%) rename {trace_decoder/src => evm_arithmetization/src/world}/world.rs (91%) diff --git a/Cargo.lock b/Cargo.lock index 368945802..9e4f452f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1104,6 +1104,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -1856,6 +1857,9 @@ name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -2030,9 +2034,17 @@ dependencies = [ name = "evm_arithmetization" version = "0.4.0" dependencies = [ + "alloy", + "alloy-compat", "anyhow", + "bitflags 2.6.0", + "bitvec", "bytes", + "ciborium", + "ciborium-io", + "copyvec", "criterion", + "either", "env_logger 0.11.5", "ethereum-types", "hashbrown", @@ -2045,6 +2057,7 @@ dependencies = [ "mpt_trie", "num", "num-bigint", + "nunny", "once_cell", "pest", "pest_derive", @@ -2061,6 +2074,7 @@ dependencies = [ "serde_json", "sha2", "smt_trie", + "stackstack", "starky", "static_assertions", "thiserror", @@ -2068,7 +2082,9 @@ dependencies = [ "tokio", "tower-lsp", "tracing", + "u4", "url", + "winnow", "zk_evm_common", "zk_evm_proc_macro", ] diff --git a/Cargo.toml b/Cargo.toml index 3b038ff26..a9bbf5b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ anyhow = "1.0.86" async-stream = "0.3.5" axum = "0.7.5" bitflags = "2.5.0" -bitvec = "1.0.1" +bitvec = { version = "1.0.1", features = ["serde"] } bytes = "1.6.0" ciborium = "0.2.2" ciborium-io = "0.2.2" @@ -47,7 +47,7 @@ clap = { version = "4.5.7", features = ["derive", "env"] } compat = { path = "compat" } criterion = "0.5.1" dotenvy = "0.15.7" -either = "1.12.0" +either = { version = "1.12.0", features = ["serde"] } enum-as-inner = "0.6.0" env_logger = "0.11.3" eth_trie = "0.4.0" diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index 0eb5457ad..da246340d 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -15,10 +15,18 @@ homepage.workspace = true keywords.workspace = true [dependencies] +alloy.workspace = true +alloy-compat = "0.1.0" anyhow.workspace = true +bitvec.workspace = true +bitflags.workspace = true bytes.workspace = true +ciborium.workspace = true +ciborium-io.workspace = true +copyvec = "0.2.0" env_logger.workspace = true ethereum-types.workspace = true +either.workspace = true hashbrown.workspace = true hex = { workspace = true, optional = true } hex-literal.workspace = true @@ -29,6 +37,7 @@ log.workspace = true mpt_trie.workspace = true num.workspace = true num-bigint.workspace = true +nunny = "0.2.1" once_cell.workspace = true pest.workspace = true pest_derive.workspace = true @@ -46,12 +55,15 @@ sha2.workspace = true smt_trie = { workspace = true, optional = true } starky = { workspace = true, features = ["parallel"] } static_assertions.workspace = true +stackstack = "0.3.0" thiserror.workspace = true tiny-keccak.workspace = true tokio.workspace = true tower-lsp = "0.20.0" tracing.workspace = true +u4 = "0.1.0" url.workspace = true +winnow.workspace = true zk_evm_common.workspace = true zk_evm_proc_macro.workspace = true diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index f263c3995..9b6e814b5 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -3,6 +3,7 @@ use std::fmt::Display; use anyhow::anyhow; use ethereum_types::{Address, BigEndianHash, H256, U256}; +use itertools::Either; use keccak_hash::keccak; use log::error; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; @@ -37,6 +38,7 @@ use crate::proof::{ use crate::util::{h2u, u256_to_usize}; use crate::witness::memory::{MemoryAddress, MemoryChannel, MemoryState}; use crate::witness::state::RegistersState; +use crate::world::world::{StateWorld, Type1World, Type2World}; pub(crate) mod linked_list; pub mod mpt; @@ -121,10 +123,10 @@ pub struct GenerationInputs { /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. - #[cfg(feature = "eth_mainnet")] - pub contract_code: HashMap>, - #[cfg(feature = "cdk_erigon")] - pub contract_code: HashMap>, + // #[cfg(feature = "eth_mainnet")] + // pub contract_code: HashMap>, + // #[cfg(feature = "cdk_erigon")] + pub contract_code: HashMap, Vec>, /// Information contained in the block header. pub block_metadata: BlockMetadata, @@ -179,7 +181,7 @@ pub struct TrimmedGenerationInputs { #[cfg(feature = "eth_mainnet")] pub contract_code: HashMap>, #[cfg(feature = "cdk_erigon")] - pub contract_code: HashMap>, + pub contract_code: HashMap, Vec>, /// Information contained in the block header. pub block_metadata: BlockMetadata, @@ -196,15 +198,16 @@ pub struct TrimmedGenerationInputs { #[cfg(feature = "cdk_erigon")] type SmtTrie = smt_trie::smt::Smt; +trait StateTrie {} #[derive(Clone, Debug, Deserialize, Serialize, Default)] pub struct TrieInputs { /// A partial version of the state trie prior to these transactions. It /// should include all nodes that will be accessed by these /// transactions. - #[cfg(feature = "eth_mainnet")] - pub state_trie: HashedPartialTrie, - #[cfg(feature = "cdk_erigon")] - pub state_trie: SmtTrie, + // #[cfg(feature = "eth_mainnet")] + // pub state_trie: HashedPartialTrie, + // #[cfg(feature = "cdk_erigon")] + pub state_trie: StateWorld, /// A partial version of the transaction trie prior to these transactions. /// It should include all nodes that will be accessed by these @@ -228,15 +231,15 @@ pub struct TrimmedTrieInputs { /// A partial version of the state trie prior to these transactions. It /// should include all nodes that will be accessed by these /// transactions. - #[cfg(feature = "eth_mainnet")] - pub state_trie: HashedPartialTrie, - #[cfg(feature = "cdk_erigon")] - pub state_trie: SmtTrie, - /// A partial version of each storage trie prior to these transactions. It - /// should include all storage tries, and nodes therein, that will be - /// accessed by these transactions. - #[cfg(feature = "eth_mainnet")] - pub storage_tries: Vec<(H256, HashedPartialTrie)>, + // #[cfg(feature = "eth_mainnet")] + // pub state_trie: HashedPartialTrie, + // #[cfg(feature = "cdk_erigon")] + pub state_trie: StateWorld, + // /// A partial version of each storage trie prior to these transactions. It + // /// should include all storage tries, and nodes therein, that will be + // /// accessed by these transactions. + // #[cfg(feature = "eth_mainnet")] + // pub storage_tries: Vec<(H256, HashedPartialTrie)>, } impl TrieInputs { @@ -273,8 +276,13 @@ impl GenerationInputs { } #[cfg(feature = "cdk_erigon")] { - let smt_data = self.tries.state_trie.to_vec(); - state_root = H256::from_uint(&hash_serialize_u256(&smt_data).into()); + state_root = match &self.tries.state_trie.state { + Either::Left(trie) => trie.state_trie().hash(), + Either::Right(trie) => { + let smt_data = trie.as_smt().to_vec(); + H256::from_uint(&hash_serialize_u256(&smt_data).into()) + } + } } TrimmedGenerationInputs { diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 8a66d826c..0fa48a665 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -3,6 +3,7 @@ use std::any::Any; use std::collections::{BTreeMap, HashMap}; use bytes::{Bytes, BytesMut}; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256, U256}; use keccak_hash::keccak; use mpt_trie::nibbles::{Nibbles, NibblesIntern}; @@ -680,20 +681,32 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( Ok((state_leaves, storage_leaves, trie_data)) } -#[cfg(feature = "eth_mainnet")] +// #[cfg(feature = "eth_mainnet")] pub(crate) fn load_state_mpt( trie_inputs: &TrimmedTrieInputs, trie_data: &mut Vec>, ) -> Result { - let storage_tries_by_state_key = trie_inputs - .storage_tries - .iter() - .map(|(hashed_address, storage_trie)| { - let key = Nibbles::from_bytes_be(hashed_address.as_bytes()) - .expect("An H256 is 32 bytes long"); - (key, storage_trie) - }) - .collect(); + let storage_tries_by_state_key = match &trie_inputs.state_trie.state { + Either::Left(mpt) => mpt + + .get_storage_mut().expect("There's a storage trie.") + .iter() + .map(|(hashed_address, storage_trie)| { + let key = Nibbles::from_bytes_be(hashed_address.as_bytes()) + .expect("An H256 is 32 bytes long"); + (key, storage_trie) + }) + .collect(), + Either::Right(_) => panic!("eth_mainnet expects an MPT."), + } + // .storage_tries + // .iter() + // .map(|(hashed_address, storage_trie)| { + // let key = + // Nibbles::from_bytes_be(hashed_address.as_bytes()).expect("An H256 is 32 bytes long"); + // (key, storage_trie) + // }) + // .collect(); load_state_trie( &trie_inputs.state_trie, diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 2664c663d..306069586 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -4,7 +4,7 @@ use std::collections::{BTreeSet, HashMap}; use std::str::FromStr; use anyhow::{bail, Error, Result}; -#[cfg(feature = "eth_mainnet")] +use either::Either; use ethereum_types::{BigEndianHash, H256}; use ethereum_types::{U256, U512}; use itertools::Itertools; @@ -17,7 +17,7 @@ use super::linked_list::testing::{LinkedList, ADDRESSES_ACCESS_LIST_LEN}; #[cfg(feature = "eth_mainnet")] use super::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use super::linked_list::{AccessLinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD}; -#[cfg(feature = "eth_mainnet")] +// #[cfg(feature = "eth_mainnet")] use super::mpt::load_state_mpt; use crate::cpu::kernel::cancun_constants::KZG_VERSIONED_HASH; use crate::cpu::kernel::constants::cancun_constants::{ @@ -104,40 +104,48 @@ impl GenerationState { let mut n = Err(ProgramError::ProverInputError( ProverInputError::InvalidInput, )); - #[cfg(feature = "eth_mainnet")] - { - n = load_state_mpt(&self.inputs.trimmed_tries, &mut new_content); - - self.memory.insert_preinitialized_segment( - Segment::TrieData, - crate::witness::memory::MemorySegmentState { - content: new_content, - }, - ); - } - #[cfg(feature = "cdk_erigon")] - { - n = Ok(new_content.len()); - let mut smt_data = self - .inputs - .trimmed_tries - .state_trie - .to_vec_skip_empty_node_and_add_offset(new_content.len()); - log::debug!("smt bef = {:?}", smt_data); - if smt_data.len() == 2 { - smt_data.extend([U256::zero(); 2]); + // #[cfg(feature = "eth_mainnet")] + // { + // n = load_state_mpt(&self.inputs.trimmed_tries, &mut new_content); + + // self.memory.insert_preinitialized_segment( + // Segment::TrieData, + // crate::witness::memory::MemorySegmentState { + // content: new_content, + // }, + // ); + // } + // #[cfg(feature = "cdk_erigon")] + // { + n = if cfg!(feature = "cdk_erigon") { + Ok(new_content.len()) + } else { + load_state_mpt(&self.inputs.trimmed_tries, &mut new_content) + }; + match &self.inputs.trimmed_tries.state_trie.state { + Either::Left(_) => (), + Either::Right(type2trie) => { + let mut smt_data = type2trie + .as_smt() + .to_vec_skip_empty_node_and_add_offset(new_content.len()); + log::debug!("smt bef = {:?}", smt_data); + if smt_data.len() == 2 { + smt_data.extend([U256::zero(); 2]); + } + log::debug!("initial smt = {:?}", smt_data); + log::debug!("smt len = {:?}", smt_data.len()); + let smt_data = smt_data.into_iter().map(|x| Some(x)); + new_content.extend(smt_data); } - log::debug!("initial smt = {:?}", smt_data); - log::debug!("smt len = {:?}", smt_data.len()); - let smt_data = smt_data.into_iter().map(|x| Some(x)); - new_content.extend(smt_data); - self.memory.insert_preinitialized_segment( - Segment::TrieData, - crate::witness::memory::MemorySegmentState { - content: new_content, - }, - ); - } + }; + + self.memory.insert_preinitialized_segment( + Segment::TrieData, + crate::witness::memory::MemorySegmentState { + content: new_content, + }, + ); + // } n }, Ok, @@ -258,28 +266,34 @@ impl GenerationState { /// Initializes the code segment of the given context with the code /// corresponding to the provided hash. /// Returns the length of the code. - #[cfg(feature = "eth_mainnet")] - fn run_account_code(&mut self) -> Result { - // stack: codehash, ctx, ... - let codehash = stack_peek(self, 0)?; - let context = stack_peek(self, 1)? >> CONTEXT_SCALING_FACTOR; - let context = u256_to_usize(context)?; - let mut address = MemoryAddress::new(context, Segment::Code, 0); - let code = self - .inputs - .contract_code - .get(&H256::from_uint(&codehash)) - .ok_or(ProgramError::ProverInputError(CodeHashNotFound))?; - for &byte in code { - self.memory.set(address, byte.into()); - address.increment(); - } - Ok(code.len().into()) - } - #[cfg(feature = "cdk_erigon")] + // #[cfg(feature = "eth_mainnet")] + // fn run_account_code(&mut self) -> Result { + // // stack: codehash, ctx, ... + // let codehash = stack_peek(self, 0)?; + // let context = stack_peek(self, 1)? >> CONTEXT_SCALING_FACTOR; + // let context = u256_to_usize(context)?; + // let mut address = MemoryAddress::new(context, Segment::Code, 0); + // let code = self + // .inputs + // .contract_code + // .get(&H256::from_uint(&codehash)) + // .ok_or(ProgramError::ProverInputError(CodeHashNotFound))?; + // for &byte in code { + // self.memory.set(address, byte.into()); + // address.increment(); + // } + // Ok(code.len().into()) + // } + // #[cfg(feature = "cdk_erigon")] fn run_account_code(&mut self) -> Result { // stack: codehash, ctx, ... + let codehash = stack_peek(self, 0)?; + let codehash = if cfg!(feature = "cdk_erigon") { + Either::Right(codehash) + } else { + Either::Left(H256::from_uint(&codehash)) + }; let context = stack_peek(self, 1)? >> CONTEXT_SCALING_FACTOR; let context = u256_to_usize(context)?; let mut address = MemoryAddress::new(context, Segment::Code, 0); @@ -440,8 +454,8 @@ impl GenerationState { ); log::debug!("state btree = {:#?}", self.inputs.trimmed_tries.state_trie); log::debug!( - "input state popopo = {}", - self.inputs.trimmed_tries.state_trie + "input state popopo = {:?}", + self.inputs.trimmed_tries.state_trie.state ); } diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 0f1f21701..ea3eaa21f 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, HashMap}; use std::mem::size_of; use anyhow::{anyhow, bail}; +use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; use itertools::Itertools; use keccak_hash::keccak; @@ -478,6 +479,10 @@ impl GenerationState { .to_vec(); trie_inputs .state_trie + .state + .clone() + .expect_right("cdk_erigon requires SMTs.") + .as_smt() .load_linked_list_data::<{ Segment::AccountsLinkedList as usize }>( &mut state_linked_list_data, &mut self.state_pointers.state, @@ -599,13 +604,19 @@ impl GenerationState { self.observe_address(tip_h160); } else if dst == KERNEL.global_labels["observe_new_contract"] { let tip_u256 = stack_peek(self, 0)?; - #[cfg(feature = "eth_mainnet")] - { - let tip_h256 = H256::from_uint(&tip_u256); - self.observe_contract(tip_h256)?; - } - #[cfg(feature = "cdk_erigon")] - self.observe_contract(tip_u256)?; + let tip_either = if cfg!(feature = "cdk_erigon") { + Either::Right(tip_u256) + } else { + Either::Left(H256::from_uint(&tip_u256)) + }; + self.observe_contract(tip_either)?; + // #[cfg(feature = "eth_mainnet")] + // { + // let tip_h256 = H256::from_uint(&tip_u256); + // self.observe_contract(tip_h256)?; + // } + // #[cfg(feature = "cdk_erigon")] + // self.observe_contract(tip_u256)?; } Ok(()) @@ -645,7 +656,10 @@ impl GenerationState { Ok(()) } #[cfg(feature = "cdk_erigon")] - pub(crate) fn observe_contract(&mut self, codehash: U256) -> Result<(), ProgramError> { + pub(crate) fn observe_contract( + &mut self, + codehash: either::Either, + ) -> Result<(), ProgramError> { if self.inputs.contract_code.contains_key(&codehash) { return Ok(()); // Return early if the code hash has already been // observed. @@ -661,7 +675,12 @@ impl GenerationState { .iter() .map(|x| x.unwrap_or_default().low_u32() as u8) .collect::>(); - debug_assert_eq!(hash_bytecode_u256(code.clone()), codehash); + let hash = if cfg!(feature = "cdk_erigon") { + Either::Left(keccak(&code)) + } else { + Either::Right(hash_bytecode_u256(code.clone())) + }; + debug_assert_eq!(hash, codehash); self.inputs.contract_code.insert(codehash, code); diff --git a/evm_arithmetization/src/lib.rs b/evm_arithmetization/src/lib.rs index 41b7f093a..387ab0eee 100644 --- a/evm_arithmetization/src/lib.rs +++ b/evm_arithmetization/src/lib.rs @@ -285,6 +285,7 @@ pub mod curve_pairings; pub mod extension_tower; pub mod testing_utils; pub mod util; +pub mod world; // Public definitions and re-exports mod public_types; diff --git a/evm_arithmetization/src/world/mod.rs b/evm_arithmetization/src/world/mod.rs new file mode 100644 index 000000000..d123c3204 --- /dev/null +++ b/evm_arithmetization/src/world/mod.rs @@ -0,0 +1,46 @@ +pub mod tries; +pub mod type1; +pub mod type2; +pub mod wire; +pub mod world; + +/// Like `#[serde(with = "hex")`, but tolerates and emits leading `0x` prefixes +mod hex { + use alloy::hex; + use serde::{de::Error as _, Deserialize as _, Deserializer, Serializer}; + + pub fn serialize(data: T, serializer: S) -> Result + where + T: hex::ToHex, + { + let s = data.encode_hex::(); + serializer.serialize_str(&format!("0x{}", s)) + } + + pub fn deserialize<'de, D: Deserializer<'de>, T>(deserializer: D) -> Result + where + T: hex::FromHex, + T::Error: std::fmt::Display, + { + let s = String::deserialize(deserializer)?; + match s.strip_prefix("0x") { + Some(rest) => T::from_hex(rest), + None => T::from_hex(&*s), + } + .map_err(D::Error::custom) + } +} + +#[cfg(test)] +#[derive(serde::Deserialize)] +struct Case { + #[serde(with = "hex")] + pub bytes: Vec, + #[serde(deserialize_with = "h256")] + pub expected_state_root: ethereum_types::H256, +} + +#[cfg(test)] +fn h256<'de, D: serde::Deserializer<'de>>(it: D) -> Result { + Ok(ethereum_types::H256(hex::deserialize(it)?)) +} diff --git a/trace_decoder/src/tries.rs b/evm_arithmetization/src/world/tries.rs similarity index 98% rename from trace_decoder/src/tries.rs rename to evm_arithmetization/src/world/tries.rs index df9c072f7..6ed5c7825 100644 --- a/trace_decoder/src/tries.rs +++ b/evm_arithmetization/src/world/tries.rs @@ -7,10 +7,12 @@ use anyhow::ensure; use bitvec::{array::BitArray, slice::BitSlice}; use copyvec::CopyVec; use ethereum_types::{Address, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, MptAccountRlp}; use mpt_trie::partial_trie::{HashedPartialTrie, Node, OnOrphanedHashNode, PartialTrie as _}; +use serde::{Deserialize, Serialize}; use u4::{AsNibbles, U4}; +use crate::generation::mpt::MptAccountRlp; + /// Bounded sequence of [`U4`], /// used as a key for [MPT](HashedPartialTrie) types in this module. /// @@ -96,7 +98,7 @@ fn mpt_key_into_hash() { /// used as a key for SMT tries. /// /// Semantically equivalent to [`smt_trie::bits::Bits`]. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Serialize, Deserialize)] pub struct SmtKey { bits: bitvec::array::BitArray<[u8; 32]>, len: usize, @@ -273,7 +275,7 @@ impl From for HashedPartialTrie { /// Global, [`Address`] `->` [`AccountRlp`]. /// /// See -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct StateMpt { /// Values are always [`rlp`]-encoded [`AccountRlp`], /// inserted at [256 bits](MptKey::from_hash). @@ -357,7 +359,7 @@ impl From for HashedPartialTrie { /// Global, per-account. /// /// See -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct StorageTrie { untyped: HashedPartialTrie, } diff --git a/trace_decoder/src/type1.rs b/evm_arithmetization/src/world/type1.rs similarity index 93% rename from trace_decoder/src/type1.rs rename to evm_arithmetization/src/world/type1.rs index c982a1ab3..660ad970c 100644 --- a/trace_decoder/src/type1.rs +++ b/evm_arithmetization/src/world/type1.rs @@ -5,15 +5,15 @@ use std::array; use std::collections::{BTreeMap, BTreeSet}; use anyhow::{bail, ensure, Context as _}; -use either::Either; -use evm_arithmetization::generation::mpt::AccountRlp; +use itertools::Either; use keccak_hash::H256; use mpt_trie::partial_trie::OnOrphanedHashNode; use nunny::NonEmpty; use u4::U4; -use crate::tries::{MptKey, StateMpt, StorageTrie}; -use crate::wire::{Instruction, SmtLeaf}; +use crate::generation::mpt::MptAccountRlp; +use crate::world::tries::{MptKey, StateMpt, StorageTrie}; +use crate::world::wire::{Instruction, SmtLeaf}; #[derive(Debug, Clone, Default)] pub struct Frontend { @@ -68,7 +68,7 @@ fn visit( storage, code, }) => { - let account = AccountRlp { + let account = MptAccountRlp { nonce: nonce.into(), balance, storage_root: { @@ -364,23 +364,23 @@ fn finish_stack(v: &mut Vec) -> anyhow::Result { } } -#[test] -fn test_tries() { - for (ix, case) in - serde_json::from_str::>(include_str!("cases/zero_jerigon.json")) - .unwrap() - .into_iter() - .enumerate() - { - println!("case {}", ix); - let instructions = crate::wire::parse(&case.bytes).unwrap(); - let frontend = frontend(instructions).unwrap(); - assert_eq!(case.expected_state_root, frontend.state.root()); +// #[test] +// fn test_tries() { +// for (ix, case) in +// serde_json::from_str::>(include_str!("cases/ +// zero_jerigon.json")) .unwrap() +// .into_iter() +// .enumerate() +// { +// println!("case {}", ix); +// let instructions = crate::wire::parse(&case.bytes).unwrap(); +// let frontend = frontend(instructions).unwrap(); +// assert_eq!(case.expected_state_root, frontend.state.root()); - for (haddr, acct) in frontend.state.iter() { - if acct.storage_root != StorageTrie::default().root() { - assert!(frontend.storage.contains_key(&haddr)) - } - } - } -} +// for (haddr, acct) in frontend.state.iter() { +// if acct.storage_root != StorageTrie::default().root() { +// assert!(frontend.storage.contains_key(&haddr)) +// } +// } +// } +// } diff --git a/trace_decoder/src/type2.rs b/evm_arithmetization/src/world/type2.rs similarity index 92% rename from trace_decoder/src/type2.rs rename to evm_arithmetization/src/world/type2.rs index 845260d47..8bc39282e 100644 --- a/trace_decoder/src/type2.rs +++ b/evm_arithmetization/src/world/type2.rs @@ -10,7 +10,7 @@ use keccak_hash::H256; use nunny::NonEmpty; use stackstack::Stack; -use crate::{ +use crate::world::{ tries::SmtKey, wire::{Instruction, SmtLeaf, SmtLeafType}, world::{Type2Entry, Type2World}, @@ -173,17 +173,18 @@ fn visit( Ok(()) } -#[test] -fn test_tries() { - use crate::world::World as _; - for (ix, case) in - serde_json::from_str::>(include_str!("cases/hermez_cdk_erigon.json")) - .unwrap() - .into_iter() - .enumerate() - { - println!("case {}", ix); - let mut frontend = frontend(crate::wire::parse(&case.bytes).unwrap()).unwrap(); - assert_eq!(case.expected_state_root, frontend.world.root()); - } -} +// #[test] +// fn test_tries() { +// use crate::world::World as _; +// for (ix, case) in +// serde_json::from_str::>(include_str!("cases/ +// hermez_cdk_erigon.json")) .unwrap() +// .into_iter() +// .enumerate() +// { +// println!("case {}", ix); +// let mut frontend = +// frontend(crate::wire::parse(&case.bytes).unwrap()).unwrap(); +// assert_eq!(case.expected_state_root, frontend.world.root()); +// } +// } diff --git a/trace_decoder/src/wire.rs b/evm_arithmetization/src/world/wire.rs similarity index 100% rename from trace_decoder/src/wire.rs rename to evm_arithmetization/src/world/wire.rs diff --git a/trace_decoder/src/world.rs b/evm_arithmetization/src/world/world.rs similarity index 91% rename from trace_decoder/src/world.rs rename to evm_arithmetization/src/world/world.rs index 20c98b4c5..53c78d5e9 100644 --- a/trace_decoder/src/world.rs +++ b/evm_arithmetization/src/world/world.rs @@ -4,11 +4,31 @@ use alloy_compat::Compat as _; use anyhow::{ensure, Context as _}; use either::Either; use ethereum_types::{Address, BigEndianHash as _, U256}; -use evm_arithmetization::generation::mpt::AccountRlp; use keccak_hash::H256; +use mpt_trie::partial_trie::HashedPartialTrie; +use serde::{Deserialize, Serialize}; -use crate::tries::{MptKey, SmtKey, StateMpt, StorageTrie}; +use crate::generation::mpt::AccountRlp; +use crate::world::tries::{MptKey, SmtKey, StateMpt, StorageTrie}; +#[derive(Clone, Debug, Deserialize, Serialize)] +pub(crate) struct StateWorld { + pub(crate) state: Either, +} + +impl Default for StateWorld { + fn default() -> Self { + if cfg!(feature = "cdk_erigon") { + StateWorld { + state: Either::Left(Type1World::default()), + } + } else { + StateWorld { + state: Either::Right(Type2World::default()), + } + } + } +} /// The [core](crate::core) of this crate is agnostic over state and storage /// representations. /// @@ -93,7 +113,7 @@ pub(crate) trait World { fn root(&mut self) -> H256; } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct Type1World { state: StateMpt, /// Writes to storage should be reconciled with @@ -125,11 +145,21 @@ impl Type1World { let Self { state, storage } = self; (state, storage) } - fn get_storage_mut(&mut self, address: Address) -> anyhow::Result<&mut StorageTrie> { + pub(crate) fn get_storage_mut(&mut self, address: Address) -> anyhow::Result<&mut StorageTrie> { self.storage .get_mut(&keccak_hash::keccak(address)) .context("no such storage") } + pub(crate) fn get_storage(&mut self) -> Vec<(H256, HashedPartialTrie)> { + self.storage + .iter() + .map(|(key, value)| (*key, *value.as_hashed_partial_trie().clone())) + .collect::>() + // .self + // .storage + // .get_mut(&keccak_hash::keccak(address)) + // .context("no such storage") + } fn on_storage( &mut self, address: Address, @@ -347,7 +377,7 @@ impl World for Type2World { // but without the distinction, // the wire tests fail. // This may be a bug in the SMT library. -#[derive(Default, Clone, Debug)] +#[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct Type2Entry { pub balance: Option, pub nonce: Option, @@ -357,7 +387,7 @@ pub struct Type2Entry { } // This is a buffered version -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Type2World { accounts: BTreeMap, hashed_out: BTreeMap, diff --git a/trace_decoder/src/lib.rs b/trace_decoder/src/lib.rs index 1f1c87888..985d42fb1 100644 --- a/trace_decoder/src/lib.rs +++ b/trace_decoder/src/lib.rs @@ -61,56 +61,11 @@ const _DEVELOPER_DOCS: () = (); mod interface; -pub use interface::*; - -mod tries; -mod type1; -mod type2; -mod wire; -mod world; - pub use core::{entrypoint, WireDisposition}; +pub use interface::*; + mod core; /// Implementation of the observer for the trace decoder. pub mod observer; -/// Like `#[serde(with = "hex")`, but tolerates and emits leading `0x` prefixes -mod hex { - use serde::{de::Error as _, Deserialize as _, Deserializer, Serializer}; - - pub fn serialize(data: T, serializer: S) -> Result - where - T: hex::ToHex, - { - let s = data.encode_hex::(); - serializer.serialize_str(&format!("0x{}", s)) - } - - pub fn deserialize<'de, D: Deserializer<'de>, T>(deserializer: D) -> Result - where - T: hex::FromHex, - T::Error: std::fmt::Display, - { - let s = String::deserialize(deserializer)?; - match s.strip_prefix("0x") { - Some(rest) => T::from_hex(rest), - None => T::from_hex(&*s), - } - .map_err(D::Error::custom) - } -} - -#[cfg(test)] -#[derive(serde::Deserialize)] -struct Case { - #[serde(with = "hex")] - pub bytes: Vec, - #[serde(deserialize_with = "h256")] - pub expected_state_root: ethereum_types::H256, -} - -#[cfg(test)] -fn h256<'de, D: serde::Deserializer<'de>>(it: D) -> Result { - Ok(ethereum_types::H256(hex::deserialize(it)?)) -} From 50ca088c802154add303aeb871bb674d17a74665 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 4 Nov 2024 09:48:57 +0100 Subject: [PATCH 39/60] Keep adapting code --- evm_arithmetization/Cargo.toml | 6 +- .../benches/fibonacci_25m_gas.rs | 305 ++++++++++-------- .../src/cpu/kernel/constants/mod.rs | 10 +- .../src/cpu/kernel/interpreter.rs | 20 +- .../src/cpu/kernel/tests/account_code.rs | 70 ++-- .../src/cpu/kernel/tests/init_exc_stop.rs | 113 ++++--- .../src/cpu/kernel/tests/mpt/hash.rs | 4 +- .../src/cpu/kernel/tests/mpt/mod.rs | 141 +++++--- evm_arithmetization/src/generation/mod.rs | 73 +++-- evm_arithmetization/src/generation/mpt.rs | 87 +++-- .../src/generation/segments.rs | 4 - evm_arithmetization/src/generation/state.rs | 57 ++-- .../src/generation/trie_extractor.rs | 4 +- evm_arithmetization/src/testing_utils.rs | 45 +-- evm_arithmetization/src/world/mod.rs | 2 +- evm_arithmetization/src/world/tries.rs | 9 + evm_arithmetization/src/world/world.rs | 35 +- evm_arithmetization/tests/add11_yml.rs | 151 ++++++--- evm_arithmetization/tests/erc20.rs | 43 ++- evm_arithmetization/tests/erc20_type2.rs | 110 +++++-- evm_arithmetization/tests/erc721.rs | 39 ++- evm_arithmetization/tests/global_exit_root.rs | 26 +- evm_arithmetization/tests/log_opcode.rs | 54 +++- evm_arithmetization/tests/selfdestruct.rs | 39 ++- evm_arithmetization/tests/simple_transfer.rs | 36 ++- evm_arithmetization/tests/two_to_one_block.rs | 25 +- evm_arithmetization/tests/withdrawals.rs | 32 +- 27 files changed, 1042 insertions(+), 498 deletions(-) diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index da246340d..e73306979 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -52,7 +52,7 @@ serde = { workspace = true, features = ["derive"] } serde-big-array.workspace = true serde_json.workspace = true sha2.workspace = true -smt_trie = { workspace = true, optional = true } +smt_trie = { workspace = true } starky = { workspace = true, features = ["parallel"] } static_assertions.workspace = true stackstack = "0.3.0" @@ -73,10 +73,10 @@ hex.workspace = true ripemd.workspace = true [features] -default = ["cdk_erigon"] +default = ["eth_mainnet"] asmtools = ["hex"] polygon_pos = [] -cdk_erigon = ["smt_trie"] +cdk_erigon = [] eth_mainnet = [] [[bin]] diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 796d47da4..96d264530 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -4,11 +4,11 @@ //! Total number of user instructions: 7_136_858. //! Total number of loops: 2_378_952. -use std::any::Any; use std::collections::HashMap; use std::str::FromStr; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; +use either::Either; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; use ethereum_types::{Address, H256, U256}; #[cfg(feature = "cdk_erigon")] @@ -22,15 +22,14 @@ use evm_arithmetization::generation::mpt::{ use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::simulate_execution; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, update_beacon_roots_account_storage, -}; #[cfg(feature = "eth_mainnet")] use evm_arithmetization::testing_utils::{ - beacon_roots_contract_from_storage, preinitialized_state_and_storage_tries, + beacon_roots_account_nibbles, beacon_roots_contract_from_storage, + preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; -#[cfg(feature = "cdk_erigon")] -use evm_arithmetization::util::h2u; +// #[cfg(feature = "cdk_erigon")] +// use evm_arithmetization::util::h2u; +use evm_arithmetization::world::world::StateWorld; use evm_arithmetization::{Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -43,9 +42,7 @@ use plonky2::field::types::PrimeField64; #[cfg(feature = "cdk_erigon")] use smt_trie::{ code::hash_bytecode_u256, - db::{Db, MemoryDb}, - keys::{key_balance, key_code, key_code_length, key_nonce, key_storage}, - smt::Smt, + keys::{key_balance, key_code_length}, utils::hashout2u, }; @@ -92,46 +89,51 @@ fn prepare_setup() -> anyhow::Result> { let code = [ push1, 1, push1, 1, jumpdest, dup2, add, swap1, push4, 0, 0, 0, 4, jump, ]; - let code_hash = keccak(code); - #[cfg(feature = "cdk_erigon")] - let code_hash = CodeHashType::Uint(hash_bytecode_u256(code.to_vec())); + + let code_hash = if cfg!(feature = "cdk_erigon") { + CodeHashType::Uint(hash_bytecode_u256(code.to_vec())) + } else { + CodeHashType::Hash(keccak(code)) + }; + // let code_hash = keccak(code); + // #[cfg(feature = "cdk_erigon")] + // let code_hash = CodeHashType::Uint(hash_bytecode_u256(code.to_vec())); let empty_trie_root = HashedPartialTrie::from(Node::Empty).hash(); - #[cfg(feature = "eth_mainnet")] - let sender_account_before = Box::new(MptAccountRlp { - nonce: 169.into(), - balance: U256::from_dec_str("999999999998417410153631615")?, - storage_root: empty_trie_root, - code_hash: keccak(vec![]), - }); - #[cfg(feature = "eth_mainnet")] - let to_account_before = Box::new(MptAccountRlp { - nonce: 1.into(), - balance: 0.into(), - storage_root: empty_trie_root, - code_hash, - }); + // #[cfg(feature = "eth_mainnet")] + // let sender_account_before = Box::new(MptAccountRlp { + // nonce: 169.into(), + // balance: U256::from_dec_str("999999999998417410153631615")?, + // storage_root: empty_trie_root, + // code_hash: keccak(vec![]), + // }); + // #[cfg(feature = "eth_mainnet")] + // let to_account_before = Box::new(MptAccountRlp { + // nonce: 1.into(), + // balance: 0.into(), + // storage_root: empty_trie_root, + // code_hash, + // }); - #[cfg(feature = "cdk_erigon")] - let sender_account_before: Box = if cfg!(feature = "cdk_erigon") { - Box::new(SmtAccountRlp { + let sender_account_before = if cfg!(feature = "cdk_erigon") { + Either::Right(SmtAccountRlp { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, code_hash: hash_bytecode_u256(vec![]), code_length: 0.into(), }) } else { - Box::new(MptAccountRlp { + Either::Left(MptAccountRlp { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, storage_root: empty_trie_root, code_hash: keccak(vec![]), }) }; - #[cfg(feature = "cdk_erigon")] - let to_account_before: Box = if cfg!(feature = "cdk_erigon") { - Box::new(SmtAccountRlp { + + let to_account_before = if cfg!(feature = "cdk_erigon") { + Either::Right(SmtAccountRlp { nonce: 1.into(), balance: 0.into(), code_hash: get_u256_from_code_hash(code_hash.clone()) @@ -139,7 +141,7 @@ fn prepare_setup() -> anyhow::Result> { code_length: code.len().into(), }) } else { - Box::new(MptAccountRlp { + Either::Left(MptAccountRlp { nonce: 1.into(), balance: 0.into(), storage_root: empty_trie_root, @@ -148,59 +150,88 @@ fn prepare_setup() -> anyhow::Result> { }) }; + // #[cfg(feature = "cdk_erigon")] + // let sender_account_before: Box = if cfg!(feature = + // "cdk_erigon") { Box::new(SmtAccountRlp { + // nonce: 169.into(), + // balance: U256::from_dec_str("999999999998417410153631615")?, + // code_hash: hash_bytecode_u256(vec![]), + // code_length: 0.into(), + // }) + // } else { + // Box::new(MptAccountRlp { + // nonce: 169.into(), + // balance: U256::from_dec_str("999999999998417410153631615")?, + // storage_root: empty_trie_root, + // code_hash: keccak(vec![]), + // }) + // }; + // #[cfg(feature = "cdk_erigon")] + // let to_account_before: Box = if cfg!(feature = "cdk_erigon") + // { Box::new(SmtAccountRlp { + // nonce: 1.into(), + // balance: 0.into(), + // code_hash: get_u256_from_code_hash(code_hash.clone()) + // .expect("In cdk_erigon, the code_hash is a U256"), + // code_length: code.len().into(), + // }) + // } else { + // Box::new(MptAccountRlp { + // nonce: 1.into(), + // balance: 0.into(), + // storage_root: empty_trie_root, + // code_hash: get_h256_from_code_hash(code_hash.clone()) + // .expect("In eth_mainnet, the code_hash is a H256"), + // }) + // }; + + let mut state_trie_before = StateWorld::default(); #[cfg(feature = "eth_mainnet")] let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; #[cfg(feature = "eth_mainnet")] let mut beacon_roots_account_storage = storage_tries[0].1.clone(); #[cfg(feature = "eth_mainnet")] { - state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + let sender_account_before_mpt = + sender_account_before.expect_left("The sender account is an MPT."); + state_trie_before.insert( + sender_nibbles, + rlp::encode(&sender_account_before_mpy).to_vec(), + )?; state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; storage_tries.push((sender_state_key, Node::Empty.into())); storage_tries.push((to_state_key, Node::Empty.into())); } - #[cfg(feature = "cdk_erigon")] - let mut smt_before: Smt = Smt::default(); + #[cfg(feature = "cdk_erigon")] { + let sender_account_before_smt = + sender_account_before.expect_right("The sender account is an SMT."); + let to_account_before_smt = to_account_before.expect_right("The sender account is an SMT."); set_account( - &mut smt_before, + &mut state_trie_before, H160(sender), - sender_account_before - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT."), - &HashMap::new(), + &sender_account_before_smt, + &vec![], ); set_account( - &mut smt_before, + &mut state_trie_before, H160(to), - to_account_before - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT."), - &HashMap::new(), + &to_account_before_smt, + &code, ); - let sender_account_after = SmtAccountRlp { - nonce: sender_account_before.get_nonce() + 1, - balance: sender_account_before.get_balance(), - ..*sender_account_before - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT.") - }; } let tries_before = TrieInputs { - #[cfg(feature = "eth_mainnet")] + // #[cfg(feature = "eth_mainnet")] + // state_trie: state_trie_before, + // #[cfg(feature = "cdk_erigon")] state_trie: state_trie_before, - #[cfg(feature = "cdk_erigon")] - state_trie: smt_before, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - #[cfg(feature = "eth_mainnet")] - storage_tries, + // #[cfg(feature = "eth_mainnet")] + // storage_tries, }; let gas_used = U256::from(0x17d7840_u32); @@ -223,45 +254,55 @@ fn prepare_setup() -> anyhow::Result> { }; let mut contract_code = HashMap::new(); - #[cfg(feature = "eth_mainnet")] - { - contract_code.insert(keccak(vec![]), vec![]); + if cfg!(feature = "eth_mainnet") { + let empty_code_hash = Either::Left(keccak(vec![])); + let code_hash = Either::Left(keccak(code)); + contract_code.insert(empty_code_hash, vec![]); + contract_code.insert(code_hash, code.to_vec()); + } else { + let empty_code_hash = Either::Right(hash_bytecode_u256(vec![])); + let code_hash = Either::Right(hash_bytecode_u256(code.to_vec())); + contract_code.insert(empty_code_hash, vec![]); contract_code.insert(code_hash, code.to_vec()); } - #[cfg(feature = "cdk_erigon")] - { - contract_code.insert(hash_bytecode_u256(vec![]), vec![]); - contract_code.insert( - get_u256_from_code_hash(code_hash).expect("In cdk_erigon, the code_hash is a U256"), - code.to_vec(), - ); - } + // #[cfg(feature = "eth_mainnet")] + // { + // contract_code.insert(keccak(vec![]), vec![]); + // contract_code.insert(code_hash, code.to_vec()); + // } + // #[cfg(feature = "cdk_erigon")] + // { + // contract_code.insert(hash_bytecode_u256(vec![]), vec![]); + // contract_code.insert( + // get_u256_from_code_hash(code_hash).expect("In cdk_erigon, the + // code_hash is a U256"), code.to_vec(), + // ); + // } - let sender_account_after: Box = if cfg!(feature = "cdk_erigon") { - Box::new(SmtAccountRlp { - balance: sender_account_before.get_balance() + let sender_account_after = if cfg!(feature = "cdk_erigon") { + let sender_account_before_smt = + sender_account_before.expect_right("cdk_erigon expects SMTs."); + Either::Right(SmtAccountRlp { + balance: sender_account_before_smt.get_balance() - value - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before.get_nonce() + 1, - ..*sender_account_before - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT.") + nonce: sender_account_before_smt.get_nonce() + 1, + ..sender_account_before_smt }) } else { - Box::new(MptAccountRlp { - balance: sender_account_before.get_balance() + let sender_account_before_mpt = + sender_account_before.expect_left("eth_mainnet expects MPTs."); + Either::Left(MptAccountRlp { + balance: sender_account_before_mpt.get_balance() - value - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before.get_nonce() + 1, - ..*sender_account_before - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT.") + nonce: sender_account_before_mpt.get_nonce() + 1, + ..sender_account_before_mpt }) }; let to_account_after = &to_account_before; + let mut expected_state_trie_after = StateWorld::default(); #[cfg(feature = "eth_mainnet")] let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); #[cfg(feature = "eth_mainnet")] @@ -282,27 +323,23 @@ fn prepare_setup() -> anyhow::Result> { rlp::encode(&beacon_roots_account).to_vec(), )?; } - #[cfg(feature = "cdk_erigon")] - let mut expected_smt_after: Smt<_> = Smt::default(); + #[cfg(feature = "cdk_erigon")] { - set_account::( - &mut expected_smt_after, + let sender_account_after_smt = + sender_account_after.expect_right("cdk_erigon expects an SMT."); + let to_account_after_smt = to_account_after.expect_right("cdk_erigon expects an SMT."); + set_account( + &mut expected_state_trie_after, H160(sender), - sender_account_after - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT."), - &HashMap::new(), + &sender_account_after_smt, + &vec![], ); set_account( - &mut expected_smt_after, + &mut expected_state_trie_after, H160(to), - to_account_before - .as_any() - .downcast_ref::() - .expect("The sender account is an SMT."), - &HashMap::new(), + &to_account_after_smt, + &code, ); } @@ -323,11 +360,27 @@ fn prepare_setup() -> anyhow::Result> { } .into(); + let state_root = if cfg!(feature = "eth_mainnet") { + expected_state_trie_after + .state + .expect_left("eth_mainnet expects MPTs.") + .state_trie() + .hash() + } else { + H256::from_uint(&hashout2u( + expected_state_trie_after + .state + .expect_right("cdk_erigon expects SMTs.") + .as_smt() + .root, + )) + }; let trie_roots_after = TrieRoots { - #[cfg(feature = "eth_mainnet")] - state_root: expected_state_trie_after.hash(), - #[cfg(feature = "cdk_erigon")] - state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), + // #[cfg(feature = "eth_mainnet")] + // state_root: expected_state_trie_after.hash(), + // #[cfg(feature = "cdk_erigon")] + // state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), + state_root, transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), }; @@ -365,12 +418,9 @@ criterion_main!(benches); use evm_arithmetization::generation::mpt::SmtAccountRlp; #[cfg(feature = "cdk_erigon")] -fn set_account( - smt: &mut Smt, - addr: Address, - account: &SmtAccountRlp, - storage: &HashMap, -) { +fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, code: &[u8]) { + use evm_arithmetization::world::world::World; + let key = key_balance(addr); log::debug!( "setting {:?} balance to {:?}, the key is {:?}", @@ -378,17 +428,20 @@ fn set_account( account.get_balance(), U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) ); - smt.set(key_balance(addr), account.get_balance()); - smt.set(key_nonce(addr), account.get_nonce()); - smt.set(key_code(addr), account.get_code_hash_u256()); - let key = key_code_length(addr); - log::debug!( - "setting {:?} code length, the key is {:?}", - addr, - U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) - ); - smt.set(key_code_length(addr), account.code_length); - for (&k, &v) in storage { - smt.set(key_storage(addr, k), v); + if let Either::Right(ref mut smt_state) = world.state { + smt_state.update_balance(addr, |b| *b = account.get_balance()); + smt_state.update_nonce(addr, |n| *n = account.get_nonce()); + smt_state.set_code_hash(addr, code); + let key = key_code_length(addr); + log::debug!( + "setting {:?} code length, the key is {:?}", + addr, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); } + + // smt.set(key_code_length(addr), account.code_length); + // for (&k, &v) in storage { + // smt.set(key_storage(addr, k), v); + // } } diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index fc3a65131..e4a107050 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -431,6 +431,7 @@ const LINKED_LISTS_CONSTANTS: [(&str, u16); 8] = [ pub mod cancun_constants { use super::*; + use crate::generation::mpt::MptAccountRlp; pub const BLOB_BASE_FEE_UPDATE_FRACTION: U256 = U256([0x32f0ed, 0, 0, 0]); @@ -477,8 +478,8 @@ pub mod cancun_constants { pub const BEACON_ROOTS_CONTRACT_CODE_HASH: [u8; 32] = hex!("f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c"); - #[cfg(feature = "eth_mainnet")] - pub const BEACON_ROOTS_ACCOUNT: AccountRlp = AccountRlp { + // #[cfg(feature = "eth_mainnet")] + pub const BEACON_ROOTS_ACCOUNT: MptAccountRlp = MptAccountRlp { nonce: U256::zero(), balance: U256::zero(), // Storage root for this account at genesis. @@ -499,6 +500,7 @@ pub mod cancun_constants { pub mod global_exit_root { use super::*; + use crate::generation::mpt::MptAccountRlp; /// Taken from . pub const GLOBAL_EXIT_ROOT_MANAGER_L2: (&str, [u8; 20]) = ( @@ -540,8 +542,8 @@ pub mod global_exit_root { pub const GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH: [u8; 32] = hex!("6bec2bf64f7e824109f6ed55f77dd7665801d6195e461666ad6a5342a9f6daf5"); - #[cfg(feature = "eth_mainnet")] - pub const GLOBAL_EXIT_ROOT_ACCOUNT: AccountRlp = AccountRlp { + // #[cfg(feature = "eth_mainnet")] + pub const GLOBAL_EXIT_ROOT_ACCOUNT: MptAccountRlp = MptAccountRlp { nonce: U256::zero(), balance: U256::zero(), // Empty storage root diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index f4354eb0c..760ed0dbc 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -8,6 +8,7 @@ use std::collections::{BTreeSet, HashMap}; use anyhow::anyhow; +use either::Either; use ethereum_types::{BigEndianHash, U256}; use log::Level; use mpt_trie::partial_trie::PartialTrie; @@ -301,9 +302,22 @@ impl Interpreter { GlobalMetadata::StateTrieRootDigestBefore, // TODO: We should reuse the serilized trie in memory. #[cfg(feature = "eth_mainnet")] - h2u(tries.state_trie.hash()), + h2u(tries + .state_trie + .state + .clone() + .expect_left("eth_mainnet expects MPTs.") + .state_trie() + .hash()), #[cfg(feature = "cdk_erigon")] - hash_serialize_u256(&tries.state_trie.to_vec()), + hash_serialize_u256(&smt.as_smt().to_vec()), + /* match &tries.state_trie.state { + * Either::Left(mpt) => + * h2u(mpt.state_trie().hash()), + * Either::Right(smt) => + * hash_serialize_u256(&smt. + * as_smt().to_vec()), + * }, */ ), ( GlobalMetadata::TransactionTrieRootDigestBefore, @@ -493,7 +507,7 @@ impl Interpreter { #[cfg(feature = "eth_mainnet")] fn insert_preinitialized_segment(&mut self, segment: Segment, values: MemorySegmentState) { self.generation_state - .memorys + .memory .insert_preinitialized_segment(segment, values); } diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 93ec2c6f1..d6bf0f004 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use anyhow::Result; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256, U256}; use hex_literal::hex; use keccak_hash::keccak; @@ -26,6 +27,7 @@ use crate::memory::segments::Segment; use crate::util::h2u; use crate::witness::memory::MemoryAddress; use crate::witness::operation::CONTEXT_SCALING_FACTOR; +use crate::world::world::StateWorld; pub(crate) fn initialize_mpts( interpreter: &mut Interpreter, @@ -159,14 +161,14 @@ pub(crate) fn prepare_interpreter( let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; let mut state_trie: HashedPartialTrie = HashedPartialTrie::from(Node::Empty); let trie_inputs = TrieInputs { - #[cfg(feature = "eth_mainnet")] - state_trie: HashedPartialTrie::from(Node::Empty), - #[cfg(feature = "cdk_erigon")] - state_trie: Smt::default(), + // #[cfg(feature = "eth_mainnet")] + // state_trie: HashedPartialTrie::from(Node::Empty), + // #[cfg(feature = "cdk_erigon")] + state_trie: StateWorld::default(), transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), - #[cfg(feature = "eth_mainnet")] - storage_tries: vec![], + // #[cfg(feature = "eth_mainnet")] + // storage_tries: vec![], }; initialize_mpts(interpreter, &trie_inputs); @@ -318,16 +320,24 @@ fn test_extcodesize() -> Result<()> { interpreter .push(U256::from_big_endian(address.as_bytes())) .expect("The stack should not overflow"); - #[cfg(feature = "eth_mainnet")] - { - interpreter.generation_state.inputs.contract_code = - HashMap::from([(keccak(&code), code.clone())]); - } - #[cfg(feature = "cdk_erigon")] - { - interpreter.generation_state.inputs.contract_code = - HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); - } + interpreter.generation_state.inputs.contract_code = if cfg!(feature = "eth_mainnet") { + HashMap::from([(Either::Left(keccak(&code)), code.clone())]) + } else { + HashMap::from([( + Either::Right(hash_bytecode_u256(code.clone())), + code.clone(), + )]) + }; + // #[cfg(feature = "eth_mainnet")] + // { + // interpreter.generation_state.inputs.contract_code = + // HashMap::from([(keccak(&code), code.clone())]); + // } + // #[cfg(feature = "cdk_erigon")] + // { + // interpreter.generation_state.inputs.contract_code = + // HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); + // } interpreter.run()?; @@ -401,16 +411,24 @@ fn test_extcodecopy() -> Result<()> { interpreter .push((0xDEADBEEFu64 + (1 << 32)).into()) .expect("The stack should not overflow"); // kexit_info - #[cfg(feature = "eth_mainnet")] - { - interpreter.generation_state.inputs.contract_code = - HashMap::from([(keccak(&code), code.clone())]); - } - #[cfg(feature = "cdk_erigon")] - { - interpreter.generation_state.inputs.contract_code = - HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); - } + interpreter.generation_state.inputs.contract_code = if cfg!(feature = "eth_mainnet") { + HashMap::from([(Either::Left(keccak(&code)), code.clone())]) + } else { + HashMap::from([( + Either::Right(hash_bytecode_u256(code.clone())), + code.clone(), + )]) + }; + // #[cfg(feature = "eth_mainnet")] + // { + // interpreter.generation_state.inputs.contract_code = + // HashMap::from([(keccak(&code), code.clone())]); + // } + // #[cfg(feature = "cdk_erigon")] + // { + // interpreter.generation_state.inputs.contract_code = + // HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); + // } interpreter.run()?; diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs index ba0d46311..36c48ad4b 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -1,12 +1,12 @@ -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; +use either::Either; use ethereum_types::{BigEndianHash, U256}; use keccak_hash::{keccak, H256}; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::field::types::Field; -#[cfg(feature = "cdk_erigon")] -use smt_trie::{code::hash_bytecode_u256, db::MemoryDb, smt::Smt, utils::hashout2u}; +use smt_trie::{code::hash_bytecode_u256, utils::hashout2u}; use crate::cpu::kernel::{aggregator::KERNEL, interpreter::Interpreter}; use crate::generation::{ @@ -20,6 +20,8 @@ use crate::testing_utils::{ preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use crate::witness::{memory::MemoryAddress, state::RegistersState}; +use crate::world::tries::{StateMpt, StorageTrie}; +use crate::world::world::{StateWorld, Type1World}; use crate::EMPTY_CONSOLIDATED_BLOCKHASH; use crate::{ proof::{BlockHashes, BlockMetadata, TrieRoots}, @@ -48,51 +50,90 @@ fn test_init_exc_stop() { ..Default::default() }; - #[cfg(feature = "cdk_erigon")] - let state_trie_before = Smt::default(); + // #[cfg(feature = "cdk_erigon")] + let state_trie_before = StateWorld::default(); let transactions_trie = HashedPartialTrie::from(Node::Empty); let receipts_trie = HashedPartialTrie::from(Node::Empty); + // #[cfg(feature = "cdk_erigon")] + let mut expected_state_trie_after = StateWorld::default(); #[cfg(feature = "eth_mainnet")] - let (state_trie_before, storage_tries) = preinitialized_state_and_storage_tries().unwrap(); + let (state_trie_before_hashed, storage_tries) = + preinitialized_state_and_storage_tries().unwrap(); #[cfg(feature = "eth_mainnet")] - let mut beacon_roots_account_storage = storage_tries[0].1.clone(); - #[cfg(feature = "eth_mainnet")] - let expected_state_trie_after = { - update_beacon_roots_account_storage( - &mut beacon_roots_account_storage, - block_metadata.block_timestamp, - block_metadata.parent_beacon_block_root, + { + let mut type1world = Type1World::new( + StateMpt::new_with_inner(state_trie_before_hashed), + BTreeMap::default(), ) .unwrap(); - let beacon_roots_account = - beacon_roots_contract_from_storage(&beacon_roots_account_storage); - - let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after - .insert( - beacon_roots_account_nibbles(), - rlp::encode(&beacon_roots_account).to_vec(), + let mut init_storage = BTreeMap::default(); + for (storage, v) in &storage_tries { + init_storage.insert(*storage, StorageTrie::new_with_trie(v.clone())); + } + type1world.set_storage(init_storage); + } + + #[cfg(feature = "eth_mainnet")] + let mut beacon_roots_account_storage = storage_tries[0].1.clone(); + #[cfg(feature = "eth_mainnet")] + { + expected_state_trie_after = { + update_beacon_roots_account_storage( + &mut beacon_roots_account_storage, + block_metadata.block_timestamp, + block_metadata.parent_beacon_block_root, ) .unwrap(); - expected_state_trie_after - }; - - #[cfg(feature = "cdk_erigon")] - let expected_state_trie_after: Smt = Smt::default(); + let beacon_roots_account = + beacon_roots_contract_from_storage(&beacon_roots_account_storage); + + let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); + expected_state_trie_after + .insert( + beacon_roots_account_nibbles(), + rlp::encode(&beacon_roots_account).to_vec(), + ) + .unwrap(); + let mut type1world = Type1World::new( + StateMpt::new_with_inner(expected_state_trie_after), + BTreeMap::default(), + ) + .unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } + }; + } let mut contract_code = HashMap::new(); - #[cfg(feature = "eth_mainnet")] - contract_code.insert(keccak(vec![]), vec![]); - #[cfg(feature = "cdk_erigon")] - contract_code.insert(hash_bytecode_u256(vec![]), vec![]); + // #[cfg(feature = "eth_mainnet")] + // contract_code.insert(keccak(vec![]), vec![]); + // #[cfg(feature = "cdk_erigon")] + // contract_code.insert(hash_bytecode_u256(vec![]), vec![]); + let contract_hash = if cfg!(feature = "eth_mainnet") { + Either::Left(keccak(vec![])) + } else { + Either::Right(hash_bytecode_u256(vec![])) + }; + contract_code.insert(contract_hash, vec![]); + let state_root = match &expected_state_trie_after.state { + Either::Left(type1world) => type1world.state_trie().hash(), + Either::Right(type2world) => H256::from_uint(&hashout2u(type2world.as_smt().root)), + }; let trie_roots_after = TrieRoots { - #[cfg(feature = "cdk_erigon")] - state_root: H256::from_uint(&hashout2u(expected_state_trie_after.root)), - #[cfg(feature = "eth_mainnet")] - state_root: expected_state_trie_after.hash(), + // #[cfg(feature = "cdk_erigon")] + // state_root: H256::from_uint(&hashout2u(expected_state_trie_after.root)), + // #[cfg(feature = "eth_mainnet")] + // state_root: expected_state_trie_after.hash(), + state_root, transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), }; @@ -105,8 +146,8 @@ fn test_init_exc_stop() { state_trie: state_trie_before, transactions_trie, receipts_trie, - #[cfg(feature = "eth_mainnet")] - storage_tries, + // #[cfg(feature = "eth_mainnet")] + // storage_tries, }, trie_roots_after, contract_code, diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs index fdb342805..202add7e9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs @@ -19,7 +19,7 @@ fn mpt_hash_empty() -> Result<()> { state_trie: Default::default(), transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; test_state_trie(trie_inputs) @@ -37,7 +37,7 @@ fn mpt_hash_empty_branch() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; test_state_trie(trie_inputs) } diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 1ef94bbbb..76e83f362 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -1,8 +1,11 @@ +use either::Either; use ethereum_types::{BigEndianHash, H256, U256}; use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::HashedPartialTrie; use mpt_trie::partial_trie::PartialTrie; +use crate::generation::mpt::EitherRlp; +use crate::generation::mpt::MptAccountRlp; use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; use crate::Node; @@ -35,45 +38,70 @@ pub(crate) fn nibbles_count>(v: T, count: usize) -> Nibbles { } } -#[cfg(feature = "eth_mainnet")] -pub(crate) fn test_account_1() -> AccountRlp { - AccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - storage_root: H256::from_uint(&U256::from(3333)), - code_hash: H256::from_uint(&U256::from(4444)), +// #[cfg(feature = "eth_mainnet")] +pub(crate) fn test_account_1_empty_storage() -> EitherRlp { + if cfg!(feature = "cdk_erigon") { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: U256::from(4444), + code_length: 0.into(), + }), + } + } else { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: HashedPartialTrie::from(Node::Empty).hash(), + code_hash: H256::from_uint(&U256::from(4444)), + }), + } } } -#[cfg(feature = "eth_mainnet")] -pub(crate) fn test_account_1_empty_storage() -> AccountRlp { - AccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: H256::from_uint(&U256::from(4444)), +// #[cfg(feature = "eth_mainnet")] +pub(crate) fn test_account_1() -> EitherRlp { + if cfg!(feature = "cdk_erigon") { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: U256::from(4444), + code_length: 0.into(), + }), + } + } else { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: H256::from_uint(&U256::from(3333)), + code_hash: H256::from_uint(&U256::from(4444)), + }), + } } } +// #[cfg(feature = "cdk_erigon")] +// pub(crate) fn test_account_1() -> Box { +// Box::new(SmtAccountRlp { +// nonce: U256::from(1111), +// balance: U256::from(2222), +// code_hash: U256::from(4444), +// code_length: 0.into(), +// }) +// } -#[cfg(feature = "cdk_erigon")] -pub(crate) fn test_account_1() -> Box { - Box::new(SmtAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - code_hash: U256::from(4444), - code_length: 0.into(), - }) -} - -#[cfg(feature = "cdk_erigon")] -pub(crate) fn test_account_1_empty_storage() -> Box { - Box::new(SmtAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - code_hash: U256::from(4444), - code_length: 0.into(), - }) -} +// #[cfg(feature = "cdk_erigon")] +// pub(crate) fn test_account_1_empty_storage() -> Box { +// Box::new(SmtAccountRlp { +// nonce: U256::from(1111), +// balance: U256::from(2222), +// code_hash: U256::from(4444), +// code_length: 0.into(), +// }) +// } pub(crate) fn test_account_1_rlp() -> Vec { test_account_1().rlp_encode().to_vec() @@ -83,27 +111,40 @@ pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { test_account_1_empty_storage().rlp_encode().to_vec() } -#[cfg(feature = "eth_mainnet")] -pub(crate) fn test_account_2() -> Box { - MptAccountRlp { - nonce: U256::from(5555), - balance: U256::from(6666), - storage_root: H256::from_uint(&U256::from(7777)), - code_hash: H256::from_uint(&U256::from(8888)), +// #[cfg(feature = "eth_mainnet")] +pub(crate) fn test_account_2() -> EitherRlp { + if cfg!(feature = "cdk_erigon") { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: U256::from(5555), + balance: U256::from(6666), + code_hash: U256::from(8888), + code_length: 0.into(), + }), + } + } else { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: U256::from(5555), + balance: U256::from(6666), + storage_root: H256::from_uint(&U256::from(7777)), + code_hash: H256::from_uint(&U256::from(8888)), + }), + } } } -#[cfg(feature = "cdk_erigon")] -pub(crate) fn test_account_2() -> Box { - use crate::generation::mpt::SmtAccountRlp; +// #[cfg(feature = "cdk_erigon")] +// pub(crate) fn test_account_2() -> Box { +// use crate::generation::mpt::SmtAccountRlp; - Box::new(SmtAccountRlp { - nonce: U256::from(5555), - balance: U256::from(6666), - code_hash: U256::from(8888), - code_length: 0.into(), - }) -} +// Box::new(SmtAccountRlp { +// nonce: U256::from(5555), +// balance: U256::from(6666), +// code_hash: U256::from(8888), +// code_length: 0.into(), +// }) +// } pub(crate) fn test_account_2_rlp() -> Vec { test_account_2().rlp_encode().to_vec() diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 9b6e814b5..b3beb5e9f 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -14,6 +14,7 @@ use plonky2::timed; use plonky2::util::timing::TimingTree; use segments::GenerationSegmentData; use serde::{Deserialize, Serialize}; +use smt_trie::smt::hash_serialize_u256; #[cfg(feature = "cdk_erigon")] use smt_trie::smt::hash_serialize_u256; use starky::config::StarkConfig; @@ -178,9 +179,9 @@ pub struct TrimmedGenerationInputs { /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. - #[cfg(feature = "eth_mainnet")] - pub contract_code: HashMap>, - #[cfg(feature = "cdk_erigon")] + // #[cfg(feature = "eth_mainnet")] + // pub contract_code: HashMap>, + // #[cfg(feature = "cdk_erigon")] pub contract_code: HashMap, Vec>, /// Information contained in the block header. @@ -218,12 +219,11 @@ pub struct TrieInputs { /// should include all nodes that will be accessed by these /// transactions. pub receipts_trie: HashedPartialTrie, - - /// A partial version of each storage trie prior to these transactions. It - /// should include all storage tries, and nodes therein, that will be - /// accessed by these transactions. - #[cfg(feature = "eth_mainnet")] - pub storage_tries: Vec<(H256, HashedPartialTrie)>, + // /// A partial version of each storage trie prior to these transactions. It + // /// should include all storage tries, and nodes therein, that will be + // /// accessed by these transactions. + // #[cfg(feature = "eth_mainnet")] + // pub storage_tries: Vec<(H256, HashedPartialTrie)>, } #[derive(Clone, Debug, Deserialize, Serialize, Default)] @@ -243,14 +243,14 @@ pub struct TrimmedTrieInputs { } impl TrieInputs { - #[cfg(feature = "eth_mainnet")] - pub(crate) fn trim(&self) -> TrimmedTrieInputs { - TrimmedTrieInputs { - state_trie: self.state_trie.clone(), - storage_tries: self.storage_tries.clone(), - } - } - #[cfg(feature = "cdk_erigon")] + // #[cfg(feature = "eth_mainnet")] + // pub(crate) fn trim(&self) -> TrimmedTrieInputs { + // TrimmedTrieInputs { + // state_trie: self.state_trie.clone(), + // // storage_tries: self.storage_tries.clone(), + // } + // } + // #[cfg(feature = "cdk_erigon")] pub(crate) fn trim(&self) -> TrimmedTrieInputs { TrimmedTrieInputs { state_trie: self.state_trie.clone(), @@ -269,21 +269,21 @@ impl GenerationInputs { .map(|tx_bytes| keccak(&tx_bytes[..])) .collect(); - let mut state_root = H256::zero(); - #[cfg(feature = "eth_mainnet")] - { - state_root = self.tries.state_trie.hash(); - } - #[cfg(feature = "cdk_erigon")] - { - state_root = match &self.tries.state_trie.state { - Either::Left(trie) => trie.state_trie().hash(), - Either::Right(trie) => { - let smt_data = trie.as_smt().to_vec(); - H256::from_uint(&hash_serialize_u256(&smt_data).into()) - } + // let mut state_root = H256::zero(); + // #[cfg(feature = "eth_mainnet")] + // { + // state_root = self.tries.state_trie.hash(); + // } + // #[cfg(feature = "cdk_erigon")] + // { + let state_root = match &self.tries.state_trie.state { + Either::Left(trie) => trie.state_trie().hash(), + Either::Right(trie) => { + let smt_data = trie.as_smt().to_vec(); + H256::from_uint(&hash_serialize_u256(&smt_data).into()) } - } + }; + // } TrimmedGenerationInputs { trimmed_tries: self.tries.trim(), @@ -489,7 +489,16 @@ pub(crate) fn debug_inputs(inputs: &GenerationInputs) { ); log::debug!("Input receipts_trie: {:?}", &inputs.tries.receipts_trie); #[cfg(feature = "eth_mainnet")] - log::debug!("Input storage_tries: {:?}", &inputs.tries.storage_tries); + log::debug!( + "Input storage_tries: {:?}", + &inputs + .tries + .state_trie + .state + .clone() + .expect_left("eth_mainnet expects MPTs") + .get_storage() + ); log::debug!("Input contract_code: {:?}", &inputs.contract_code); } diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 0fa48a665..46247112a 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -125,6 +125,45 @@ pub trait AccountRlp: Any { fn as_any(&self) -> &dyn Any; } +pub struct EitherRlp { + pub account_rlp: Either, +} + +impl EitherRlp { + pub(crate) fn rlp_encode(&self) -> BytesMut { + match &self.account_rlp { + Either::Left(mpt_acct) => mpt_acct.rlp_encode(), + Either::Right(smt_acct) => smt_acct.rlp_encode(), + } + } + + pub fn as_smt_account_rlp(&self) -> &SmtAccountRlp { + match &self.account_rlp { + Either::Left(_mpt_account_rlp) => panic!("cdk_erigon expects SMTs"), + Either::Right(smt_account_rlp) => smt_account_rlp, + } + } + + pub fn as_mpt_account_rlp(&self) -> &MptAccountRlp { + match &self.account_rlp { + Either::Left(mpt_account_rlp) => mpt_account_rlp, + Either::Right(_smt_account_rlp) => panic!("eth_main expects MPTs"), + } + } +} + +impl Default for EitherRlp { + fn default() -> Self { + EitherRlp { + account_rlp: if cfg!(feature = "cdk_erigon") { + Either::Right(SmtAccountRlp::default()) + } else { + Either::Left(MptAccountRlp::default()) + }, + } + } +} + #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct TrieRootPtrs { pub state_root_ptr: Option, @@ -331,7 +370,7 @@ where } } -#[cfg(feature = "eth_mainnet")] +// #[cfg(feature = "eth_mainnet")] fn load_state_trie( trie: &HashedPartialTrie, key: Nibbles, @@ -395,8 +434,9 @@ fn load_state_trie( Ok(node_ptr) } Node::Leaf { nibbles, value } => { - let account: AccountRlp = rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; - let AccountRlp { + let account: MptAccountRlp = + rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; + let MptAccountRlp { nonce, balance, storage_root, @@ -495,8 +535,9 @@ fn get_state_and_storage_leaves( Ok(()) } Node::Leaf { nibbles, value } => { - let account: AccountRlp = rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; - let AccountRlp { + let account: MptAccountRlp = + rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; + let MptAccountRlp { nonce, balance, storage_root, @@ -657,18 +698,22 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( empty_list_mem::(Segment::StorageLinkedList as usize) .to_vec(); let mut trie_data = vec![Some(U256::zero())]; - let storage_tries_by_state_key = trie_inputs - .storage_tries + let mpt_state = match &trie_inputs.state_trie.state { + Either::Left(type1world) => type1world, + Either::Right(_) => panic!("eth_mainnet expects MPTs."), + }; + let storage_tries_by_state_key = mpt_state + .get_storage() .iter() .map(|(hashed_address, storage_trie)| { let key = Nibbles::from_bytes_be(hashed_address.as_bytes()) .expect("An H256 is 32 bytes long"); - (key, storage_trie) + (key, *storage_trie) }) .collect(); get_state_and_storage_leaves( - &trie_inputs.state_trie, + &mpt_state.state_trie(), empty_nibbles(), &mut state_leaves, &mut storage_leaves, @@ -688,28 +733,24 @@ pub(crate) fn load_state_mpt( ) -> Result { let storage_tries_by_state_key = match &trie_inputs.state_trie.state { Either::Left(mpt) => mpt - - .get_storage_mut().expect("There's a storage trie.") + .get_storage() .iter() .map(|(hashed_address, storage_trie)| { let key = Nibbles::from_bytes_be(hashed_address.as_bytes()) .expect("An H256 is 32 bytes long"); - (key, storage_trie) + (key, *storage_trie) }) - .collect(), + .collect::>(), Either::Right(_) => panic!("eth_mainnet expects an MPT."), - } - // .storage_tries - // .iter() - // .map(|(hashed_address, storage_trie)| { - // let key = - // Nibbles::from_bytes_be(hashed_address.as_bytes()).expect("An H256 is 32 bytes long"); - // (key, storage_trie) - // }) - // .collect(); + }; + + let mpt_trie = match &trie_inputs.state_trie.state { + Either::Left(t) => t.state_trie(), + Either::Right(_) => panic!("eth_mainnet expects MPTs."), + }; load_state_trie( - &trie_inputs.state_trie, + mpt_trie, empty_nibbles(), trie_data, &storage_tries_by_state_key, diff --git a/evm_arithmetization/src/generation/segments.rs b/evm_arithmetization/src/generation/segments.rs index 017733b72..e60afce20 100644 --- a/evm_arithmetization/src/generation/segments.rs +++ b/evm_arithmetization/src/generation/segments.rs @@ -218,10 +218,6 @@ impl Iterator for SegmentDataIterator { Some(boxed) => { let (data, next_data) = *boxed; self.partial_next_data = next_data; - println!( - "smt in interpreter {:?}", - self.interpreter.generation_state.state_pointers.state - ); Some(Ok((self.interpreter.generation_state.inputs.clone(), data))) } // The payload was fully consumed. diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index ea3eaa21f..e9245aeda 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -8,7 +8,7 @@ use itertools::Itertools; use keccak_hash::keccak; use log::Level; use plonky2::hash::hash_types::RichField; -#[cfg(feature = "cdk_erigon")] +// #[cfg(feature = "cdk_erigon")] use smt_trie::code::hash_bytecode_u256; use super::mpt::TrieRootPtrs; @@ -632,33 +632,38 @@ impl GenerationState { /// Observe the given code hash and store the associated code. /// When called, the code corresponding to `codehash` should be stored in /// the return data. - #[cfg(feature = "eth_mainnet")] - pub(crate) fn observe_contract(&mut self, codehash: H256) -> Result<(), ProgramError> { - if self.inputs.contract_code.contains_key(&codehash) { - return Ok(()); // Return early if the code hash has already been - // observed. - } - - let ctx = self.registers.context; - let returndata_offset = ContextMetadata::ReturndataSize.unscale(); - let returndata_size_addr = - MemoryAddress::new(ctx, Segment::ContextMetadata, returndata_offset); - let returndata_size = u256_to_usize(self.memory.get_with_init(returndata_size_addr))?; - let code = self.memory.contexts[ctx].segments[Segment::Returndata.unscale()].content - [..returndata_size] - .iter() - .map(|x| x.unwrap_or_default().low_u32() as u8) - .collect::>(); - debug_assert_eq!(keccak(&code), codehash); - - self.inputs.contract_code.insert(codehash, code); - - Ok(()) - } - #[cfg(feature = "cdk_erigon")] + // #[cfg(feature = "eth_mainnet")] + // pub(crate) fn observe_contract( + // &mut self, + // codehash: Either, + // ) -> Result<(), ProgramError> { + // if self.inputs.contract_code.contains_key(&codehash) { + // return Ok(()); // Return early if the code hash has already been + // // observed. + // } + + // let ctx = self.registers.context; + // let returndata_offset = ContextMetadata::ReturndataSize.unscale(); + // let returndata_size_addr = + // MemoryAddress::new(ctx, Segment::ContextMetadata, returndata_offset); + // let returndata_size = + // u256_to_usize(self.memory.get_with_init(returndata_size_addr))?; + // let code = + // self.memory.contexts[ctx].segments[Segment::Returndata.unscale()].content + // [..returndata_size] + // .iter() + // .map(|x| x.unwrap_or_default().low_u32() as u8) + // .collect::>(); + // debug_assert_eq!(keccak(&code), codehash); + + // self.inputs.contract_code.insert(codehash, code); + + // Ok(()) + // } + // #[cfg(feature = "cdk_erigon")] pub(crate) fn observe_contract( &mut self, - codehash: either::Either, + codehash: Either, ) -> Result<(), ProgramError> { if self.inputs.contract_code.contains_key(&codehash) { return Ok(()); // Return early if the code hash has already been diff --git a/evm_arithmetization/src/generation/trie_extractor.rs b/evm_arithmetization/src/generation/trie_extractor.rs index 3af6cb6d9..eda8dafff 100644 --- a/evm_arithmetization/src/generation/trie_extractor.rs +++ b/evm_arithmetization/src/generation/trie_extractor.rs @@ -94,11 +94,13 @@ pub(crate) fn read_state_rlp_value( memory: &MemoryState, slice: &MemoryValues, ) -> Result, ProgramError> { + use super::mpt::MptAccountRlp; + let storage_trie: HashedPartialTrie = get_trie(memory, slice[2].unwrap_or_default().as_usize(), |_, x| { Ok(rlp::encode(&read_storage_trie_value(x)).to_vec()) })?; - let account = AccountRlp { + let account = MptAccountRlp { nonce: slice[0].unwrap_or_default(), balance: slice[1].unwrap_or_default(), storage_root: storage_trie.hash(), diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index 7f35eaabb..283a89d62 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -18,13 +18,16 @@ use smt_trie::smt::Smt; pub use crate::cpu::kernel::cancun_constants::*; pub use crate::cpu::kernel::constants::global_exit_root::*; -use crate::generation::{TrieInputs, TrimmedGenerationInputs}; +use crate::generation::mpt::MptAccountRlp; use crate::proof::TrieRoots; #[cfg(test)] use crate::witness::operation::Operation; use crate::{ - generation::mpt::AccountRlp, proof::BlockMetadata, util::h2u, GenerationInputs, - GenerationSegmentData, SegmentDataIterator, + generation::{TrieInputs, TrimmedGenerationInputs}, + world::world::StateWorld, +}; +use crate::{ + proof::BlockMetadata, util::h2u, GenerationInputs, GenerationSegmentData, SegmentDataIterator, }; pub const EMPTY_NODE_HASH: H256 = H256(hex!( @@ -86,8 +89,8 @@ pub fn update_beacon_roots_account_storage( /// Returns the beacon roots contract account from its provided storage trie. #[cfg(feature = "eth_mainnet")] -pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { - AccountRlp { +pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { + MptAccountRlp { storage_root: storage_trie.hash(), ..BEACON_ROOTS_ACCOUNT } @@ -164,16 +167,16 @@ pub fn update_scalable_account_storage( } #[cfg(feature = "eth_mainnet")] -pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { - AccountRlp { +pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { + MptAccountRlp { storage_root: storage_trie.hash(), ..GLOBAL_EXIT_ROOT_ACCOUNT } } #[cfg(feature = "eth_mainnet")] -pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> AccountRlp { - AccountRlp { +pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { + MptAccountRlp { storage_root: storage_trie.hash(), ..Default::default() } @@ -195,22 +198,22 @@ fn empty_payload() -> Result { // Initialize an empty state trie and storage tries let state_trie_before = HashedPartialTrie::from(crate::Node::Empty); - #[cfg(feature = "eth_mainnet")] - let storage_tries = Vec::new(); + // #[cfg(feature = "eth_mainnet")] + // let storage_tries = Vec::new(); let checkpoint_state_trie_root = state_trie_before.hash(); // Prepare the tries without any transactions or receipts - #[cfg(feature = "eth_mainnet")] - let tries_before = TrieInputs { - state_trie: state_trie_before.clone(), - storage_tries: storage_tries.clone(), - transactions_trie: HashedPartialTrie::from(crate::Node::Empty), - receipts_trie: HashedPartialTrie::from(crate::Node::Empty), - }; - - #[cfg(feature = "cdk_erigon")] + // #[cfg(feature = "eth_mainnet")] + // let tries_before = TrieInputs { + // state_trie: state_trie_before.clone(), + // storage_tries: storage_tries.clone(), + // transactions_trie: HashedPartialTrie::from(crate::Node::Empty), + // receipts_trie: HashedPartialTrie::from(crate::Node::Empty), + // }; + + // #[cfg(feature = "cdk_erigon")] let tries_before = TrieInputs { - state_trie: Smt::default(), + state_trie: StateWorld::default(), transactions_trie: HashedPartialTrie::from(crate::Node::Empty), receipts_trie: HashedPartialTrie::from(crate::Node::Empty), }; diff --git a/evm_arithmetization/src/world/mod.rs b/evm_arithmetization/src/world/mod.rs index d123c3204..d8cca7e97 100644 --- a/evm_arithmetization/src/world/mod.rs +++ b/evm_arithmetization/src/world/mod.rs @@ -5,7 +5,7 @@ pub mod wire; pub mod world; /// Like `#[serde(with = "hex")`, but tolerates and emits leading `0x` prefixes -mod hex { +pub mod hex { use alloy::hex; use serde::{de::Error as _, Deserialize as _, Deserializer, Serializer}; diff --git a/evm_arithmetization/src/world/tries.rs b/evm_arithmetization/src/world/tries.rs index 6ed5c7825..e654f8c31 100644 --- a/evm_arithmetization/src/world/tries.rs +++ b/evm_arithmetization/src/world/tries.rs @@ -304,9 +304,15 @@ impl StateMpt { ), } } + pub fn new_with_inner(inner: HashedPartialTrie) -> Self { + Self { inner } + } pub fn as_hashed_partial_trie(&self) -> &HashedPartialTrie { &self.inner } + pub fn as_mut_hashed_partial_trie(&mut self) -> &mut HashedPartialTrie { + &mut self.inner + } /// Insert a _hashed out_ part of the trie pub fn insert_hash(&mut self, key: MptKey, hash: H256) -> anyhow::Result<()> { Ok(self.inner.insert(key.into_nibbles(), hash)?) @@ -369,6 +375,9 @@ impl StorageTrie { untyped: HashedPartialTrie::new_with_strategy(Node::Empty, strategy), } } + pub fn new_with_trie(untyped: HashedPartialTrie) -> Self { + Self { untyped } + } pub fn get(&mut self, key: &MptKey) -> Option<&[u8]> { self.untyped.get(key.into_nibbles()) } diff --git a/evm_arithmetization/src/world/world.rs b/evm_arithmetization/src/world/world.rs index 53c78d5e9..a945fa9dc 100644 --- a/evm_arithmetization/src/world/world.rs +++ b/evm_arithmetization/src/world/world.rs @@ -7,34 +7,36 @@ use ethereum_types::{Address, BigEndianHash as _, U256}; use keccak_hash::H256; use mpt_trie::partial_trie::HashedPartialTrie; use serde::{Deserialize, Serialize}; +use smt_trie::code::hash_bytecode_u256; use crate::generation::mpt::AccountRlp; use crate::world::tries::{MptKey, SmtKey, StateMpt, StorageTrie}; #[derive(Clone, Debug, Deserialize, Serialize)] -pub(crate) struct StateWorld { - pub(crate) state: Either, +pub struct StateWorld { + pub state: Either, } impl Default for StateWorld { fn default() -> Self { if cfg!(feature = "cdk_erigon") { StateWorld { - state: Either::Left(Type1World::default()), + state: Either::Right(Type2World::default()), } } else { StateWorld { - state: Either::Right(Type2World::default()), + state: Either::Left(Type1World::default()), } } } } + /// The [core](crate::core) of this crate is agnostic over state and storage /// representations. /// /// This is the common interface to those data structures. /// See also [crate::_DEVELOPER_DOCS]. -pub(crate) trait World { +pub trait World { /// (State) subtries may be _hashed out. /// This type is a key which may identify a subtrie. type SubtriePath; @@ -65,6 +67,8 @@ pub(crate) trait World { /// Creates a new account at `address` if it does not exist. fn set_code(&mut self, address: Address, code: Either<&[u8], H256>) -> anyhow::Result<()>; + fn set_code_hash(&mut self, address: Address, code: &[u8]) -> anyhow::Result<()>; + /// The [core](crate::core) of this crate tracks required subtries for /// proving. /// @@ -141,6 +145,9 @@ impl Type1World { pub fn state_trie(&self) -> &mpt_trie::partial_trie::HashedPartialTrie { self.state.as_hashed_partial_trie() } + pub fn set_storage(&mut self, storage: BTreeMap) { + self.storage = storage; + } pub fn into_state_and_storage(self) -> (StateMpt, BTreeMap) { let Self { state, storage } = self; (state, storage) @@ -150,10 +157,10 @@ impl Type1World { .get_mut(&keccak_hash::keccak(address)) .context("no such storage") } - pub(crate) fn get_storage(&mut self) -> Vec<(H256, HashedPartialTrie)> { + pub(crate) fn get_storage(&self) -> Vec<(H256, &HashedPartialTrie)> { self.storage .iter() - .map(|(key, value)| (*key, *value.as_hashed_partial_trie().clone())) + .map(|(key, value)| (*key, value.as_hashed_partial_trie())) .collect::>() // .self // .storage @@ -205,6 +212,13 @@ impl World for Type1World { acct.code_hash = code.right_or_else(keccak_hash::keccak); self.state.insert(key, acct) } + fn set_code_hash(&mut self, address: Address, code: &[u8]) -> anyhow::Result<()> { + let key = keccak_hash::keccak(address); + let mut acct = self.state.get(key).unwrap_or_default(); + + acct.code_hash = keccak_hash::keccak(code); + self.state.insert(key, acct) + } fn reporting_destroy(&mut self, address: Address) -> anyhow::Result> { self.state.reporting_remove(address) } @@ -308,6 +322,13 @@ impl World for Type2World { }; Ok(()) } + fn set_code_hash(&mut self, address: Address, code: &[u8]) -> anyhow::Result<()> { + let acct = self.accounts.entry(address).or_default(); + + acct.code = Some(hash_bytecode_u256(code.to_vec())); + acct.code_length = Some(U256::from(code.len())); + Ok(()) + } fn reporting_destroy(&mut self, address: Address) -> anyhow::Result> { self.accounts.remove(&address); Ok(None) diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index dd9bfb1ce..44a3641ee 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -1,11 +1,14 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; use std::time::Duration; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; +use evm_arithmetization::generation::mpt::{ + AccountRlp, EitherRlp, LegacyReceiptRlp, MptAccountRlp, SmtAccountRlp, +}; use evm_arithmetization::generation::TrieInputs; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -14,6 +17,8 @@ use evm_arithmetization::testing_utils::{ preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World, World}; use evm_arithmetization::{ AllStark, GenerationInputs, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH, }; @@ -35,6 +40,7 @@ fn get_generation_inputs() -> GenerationInputs { let sender = hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b"); let to = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); + let rlp_default = EitherRlp::default(); let beneficiary_state_key = keccak(beneficiary); let sender_state_key = keccak(sender); let to_hashed = keccak(to); @@ -46,43 +52,63 @@ fn get_generation_inputs() -> GenerationInputs { let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; let code_hash = keccak(code); - let beneficiary_account_before = AccountRlp { - nonce: 1.into(), - ..AccountRlp::default() + let beneficiary_account_before = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + ..*rlp_default.as_mpt_account_rlp() + }), }; - let sender_account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..AccountRlp::default() + let sender_account_before = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + ..*rlp_default.as_mpt_account_rlp() + }), }; - let to_account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..AccountRlp::default() + let to_account_before = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..*rlp_default.as_mpt_account_rlp() + }), }; - let (mut state_trie_before, mut storage_tries) = + let (mut state_trie_before_hashed, mut storage_tries) = preinitialized_state_and_storage_tries().unwrap(); let mut beacon_roots_account_storage = storage_tries[0].1.clone(); - state_trie_before + state_trie_before_hashed .insert( beneficiary_nibbles, - rlp::encode(&beneficiary_account_before).to_vec(), + beneficiary_account_before + .as_mpt_account_rlp() + .rlp_encode() + .to_vec(), ) .unwrap(); - state_trie_before - .insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()) + state_trie_before_hashed + .insert( + sender_nibbles, + sender_account_before + .as_mpt_account_rlp() + .rlp_encode() + .to_vec(), + ) .unwrap(); - state_trie_before - .insert(to_nibbles, rlp::encode(&to_account_before).to_vec()) + state_trie_before_hashed + .insert( + to_nibbles, + to_account_before.as_mpt_account_rlp().rlp_encode().to_vec(), + ) .unwrap(); storage_tries.push((to_hashed, Node::Empty.into())); + let state_trie_before = get_state_world(state_trie_before_hashed, storage_tries); + let tries_before = TrieInputs { state_trie: state_trie_before.clone(), transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - storage_tries, + // storage_tries, }; let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16"); @@ -101,8 +127,10 @@ fn get_generation_inputs() -> GenerationInputs { }; let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); - contract_code.insert(code_hash, code.to_vec()); + let empty_hash_code = Either::Left(keccak(vec![])); + let code_hash_either = Either::Left(code_hash); + contract_code.insert(empty_hash_code, vec![]); + contract_code.insert(code_hash_either, code.to_vec()); let expected_state_trie_after = { update_beacon_roots_account_storage( @@ -114,39 +142,57 @@ fn get_generation_inputs() -> GenerationInputs { let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - let beneficiary_account_after = AccountRlp { - nonce: 1.into(), - ..AccountRlp::default() + let beneficiary_account_after = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + ..*rlp_default.as_mpt_account_rlp() + }), }; - let sender_account_after = AccountRlp { - balance: 0xde0b6b3a75be550u64.into(), - nonce: 1.into(), - ..AccountRlp::default() + let sender_account_after = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..*rlp_default.as_mpt_account_rlp() + }), }; - let to_account_after = AccountRlp { - balance: 0xde0b6b3a76586a0u64.into(), - code_hash, - // Storage map: { 0 => 2 } - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..AccountRlp::default() + let to_account_after = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash, + // Storage map: { 0 => 2 } + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..*rlp_default.as_mpt_account_rlp() + }), }; let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); expected_state_trie_after .insert( beneficiary_nibbles, - rlp::encode(&beneficiary_account_after).to_vec(), + beneficiary_account_after + .as_mpt_account_rlp() + .rlp_encode() + .to_vec(), ) .unwrap(); expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()) + .insert( + sender_nibbles, + sender_account_after + .as_mpt_account_rlp() + .rlp_encode() + .to_vec(), + ) .unwrap(); expected_state_trie_after - .insert(to_nibbles, rlp::encode(&to_account_after).to_vec()) + .insert( + to_nibbles, + to_account_after.as_mpt_account_rlp().rlp_encode().to_vec(), + ) .unwrap(); expected_state_trie_after .insert( @@ -191,7 +237,10 @@ fn get_generation_inputs() -> GenerationInputs { trie_roots_after, contract_code, block_metadata, - checkpoint_state_trie_root: state_trie_before.hash(), + checkpoint_state_trie_root: state_trie_before + .state + .expect_left("eth_mainnet expects MPTs.") + .root(), checkpoint_consolidated_hash: EMPTY_CONSOLIDATED_BLOCKHASH.map(F::from_canonical_u64), txn_number_before: 0.into(), gas_used_before: 0.into(), @@ -228,3 +277,19 @@ fn add11_yml() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index 2baf716e7..3d95965a9 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -1,10 +1,12 @@ #![cfg(feature = "eth_mainnet")] +use std::collections::BTreeMap; use std::str::FromStr; use std::time::Duration; +use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -13,6 +15,8 @@ use evm_arithmetization::testing_utils::{ init_logger, preinitialized_state_and_storage_tries, sd2u, update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -78,11 +82,12 @@ fn test_erc20() -> anyhow::Result<()> { (token_state_key, token_storage()?), ]); + let state_trie_before = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie: state_trie_before, transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), - storage_tries, + // storage_tries, }; let txn = signed_tx(); @@ -104,7 +109,7 @@ fn test_erc20() -> anyhow::Result<()> { }; let contract_code = [giver_bytecode(), token_bytecode(), vec![]] - .map(|v| (keccak(v.clone()), v)) + .map(|v| (Either::Left(keccak(v.clone())), v)) .into(); let expected_state_trie_after: HashedPartialTrie = { @@ -118,14 +123,14 @@ fn test_erc20() -> anyhow::Result<()> { let mut state_trie_after = HashedPartialTrie::from(Node::Empty); let sender_account = sender_account(); - let sender_account_after = AccountRlp { + let sender_account_after = MptAccountRlp { nonce: sender_account.nonce + 1, balance: sender_account.balance - gas_used * 0xa, ..sender_account }; state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; state_trie_after.insert(giver_nibbles, rlp::encode(&giver_account()?).to_vec())?; - let token_account_after = AccountRlp { + let token_account_after = MptAccountRlp { storage_root: token_storage_after()?.hash(), ..token_account()? }; @@ -249,8 +254,8 @@ fn token_storage_after() -> anyhow::Result { ]) } -fn giver_account() -> anyhow::Result { - Ok(AccountRlp { +fn giver_account() -> anyhow::Result { + Ok(MptAccountRlp { nonce: 1.into(), balance: 0.into(), storage_root: giver_storage()?.hash(), @@ -258,8 +263,8 @@ fn giver_account() -> anyhow::Result { }) } -fn token_account() -> anyhow::Result { - Ok(AccountRlp { +fn token_account() -> anyhow::Result { + Ok(MptAccountRlp { nonce: 1.into(), balance: 0.into(), storage_root: token_storage()?.hash(), @@ -267,8 +272,8 @@ fn token_account() -> anyhow::Result { }) } -fn sender_account() -> AccountRlp { - AccountRlp { +fn sender_account() -> MptAccountRlp { + MptAccountRlp { nonce: 0.into(), balance: sd2u("10000000000000000000000"), storage_root: Default::default(), @@ -291,3 +296,19 @@ fn bloom() -> [U256; 8] { .collect::>(); bloom.try_into().unwrap() } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index abfea9930..cb7d68f51 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::str::FromStr; use std::time::Duration; +use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, SmtAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; @@ -17,6 +18,7 @@ use evm_arithmetization::testing_utils::STATE_ROOT_STORAGE_POS; use evm_arithmetization::testing_utils::TIMESTAMP_STORAGE_POS; use evm_arithmetization::testing_utils::{init_logger, sd2u}; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::world::{StateWorld, Type2World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -69,27 +71,37 @@ fn test_erc20() -> anyhow::Result<()> { let giver = hex!("e7f1725E7734CE288F8367e1Bb143E90bb3F0512"); let token = hex!("5FbDB2315678afecb367f032d93F642f64180aa3"); - let mut state_smt_before = Smt::::default(); + // let mut state_smt_before = Smt::::default(); + let mut state_smt_before = StateWorld::default(); + println!("state_smt {:?}", state_smt_before); set_account( &mut state_smt_before, H160(sender), &sender_account(), &HashMap::new(), + &vec![], ); set_account( &mut state_smt_before, H160(giver), &giver_account(), &giver_storage(), + &giver_bytecode(), ); set_account( &mut state_smt_before, H160(token), &token_account(), &token_storage(), + &token_bytecode(), ); - let state_smt_before_root = state_smt_before.root; + let state_smt_before_root = state_smt_before + .state + .clone() + .expect_right("cdk_erigon expects SMTs.") + .as_smt() + .root; let tries_before = TrieInputs { state_trie: state_smt_before, @@ -116,11 +128,11 @@ fn test_erc20() -> anyhow::Result<()> { }; let contract_code = [giver_bytecode(), token_bytecode(), vec![]] - .map(|v| (hash_bytecode_u256(v.clone()), v)) + .map(|v| (Either::Right(hash_bytecode_u256(v.clone())), v)) .into(); - let expected_smt_after: Smt = { - let mut smt = Smt::default(); + let expected_smt_after: StateWorld = { + let mut smt = StateWorld::default(); let sender_account = sender_account(); let sender_account_after = SmtAccountRlp { nonce: sender_account.nonce + 1, @@ -132,13 +144,21 @@ fn test_erc20() -> anyhow::Result<()> { H160(sender), &sender_account_after, &HashMap::new(), + &vec![], + ); + set_account( + &mut smt, + H160(giver), + &giver_account(), + &giver_storage(), + &giver_bytecode(), ); - set_account(&mut smt, H160(giver), &giver_account(), &giver_storage()); set_account( &mut smt, H160(token), &token_account(), &token_storage_after(), + &token_bytecode(), ); set_account( @@ -146,6 +166,7 @@ fn test_erc20() -> anyhow::Result<()> { ADDRESS_SCALABLE_L2, &scalable_account(), &scalable_storage_after(&block_metadata, hashout2u(state_smt_before_root)), + &vec![], ); smt @@ -185,18 +206,19 @@ fn test_erc20() -> anyhow::Result<()> { .into(); let kb = key_code_length(ADDRESS_SCALABLE_L2); + let expected_smt_after_as_smt = expected_smt_after + .state + .expect_right("cdk_erigon expects SMTs.") + .as_smt(); log::debug!( "scalable code length key = {:?}", U256(std::array::from_fn(|i| kb.0[i].to_canonical_u64())) ); - log::debug!("expected smt after = {}", expected_smt_after); - log::debug!( - "expected smt data after = {:?}", - expected_smt_after.to_vec() - ); + log::debug!("expected smt after = {:?}", expected_smt_after_as_smt); + log::debug!("expected smt data after = {:?}", expected_smt_after_as_smt); let trie_roots_after = TrieRoots { - state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), + state_root: H256::from_uint(&hashout2u(expected_smt_after_as_smt.root)), transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), }; @@ -344,31 +366,63 @@ fn bloom() -> [U256; 8] { bloom.try_into().unwrap() } -fn set_account( - smt: &mut Smt, +// fn set_account( +// smt: &mut Smt, +// addr: Address, +// account: &SmtAccountRlp, +// storage: &HashMap, +// ) { +// let key = key_balance(addr); +// log::debug!( +// "setting {:?} balance to {:?}, the key is {:?}", +// addr, +// account.balance, +// U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) +// ); +// smt.set(key_balance(addr), account.balance); +// smt.set(key_nonce(addr), account.nonce); +// log::debug!("account code {:?}", account.code_hash); +// smt.set(key_code(addr), account.code_hash); +// let key = key_code_length(addr); +// log::debug!( +// "setting {:?} code length, the key is {:?}", +// addr, +// U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) +// ); +// smt.set(key_code_length(addr), account.code_length); +// for (&k, &v) in storage { +// smt.set(key_storage(addr, k), v); +// } +// } + +fn set_account( + world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, storage: &HashMap, + code: &[u8], ) { + use evm_arithmetization::world::world::World; + let key = key_balance(addr); log::debug!( "setting {:?} balance to {:?}, the key is {:?}", addr, - account.balance, + account.get_balance(), U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) ); - smt.set(key_balance(addr), account.balance); - smt.set(key_nonce(addr), account.nonce); - log::debug!("account code {:?}", account.code_hash); - smt.set(key_code(addr), account.code_hash); - let key = key_code_length(addr); - log::debug!( - "setting {:?} code length, the key is {:?}", - addr, - U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) - ); - smt.set(key_code_length(addr), account.code_length); - for (&k, &v) in storage { - smt.set(key_storage(addr, k), v); + if let Either::Right(ref mut smt_state) = world.state { + smt_state.update_balance(addr, |b| *b = account.get_balance()); + smt_state.update_nonce(addr, |n| *n = account.get_nonce()); + smt_state.set_code_hash(addr, code); + let key = key_code_length(addr); + log::debug!( + "setting {:?} code length, the key is {:?}", + addr, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); + for (&k, &v) in storage { + smt_state.store_int(addr, k, v); + } } } diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index e416dc87a..ecf931680 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -1,10 +1,12 @@ #![cfg(feature = "eth_mainnet")] +use std::collections::BTreeMap; use std::str::FromStr; use std::time::Duration; +use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -14,6 +16,8 @@ use evm_arithmetization::testing_utils::{ update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -75,11 +79,12 @@ fn test_erc721() -> anyhow::Result<()> { storage_tries.push((contract_state_key, contract_storage()?)); + let state_trie_before = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie: state_trie_before, transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), - storage_tries, + // storage_tries, }; let txn = signed_tx(); @@ -87,7 +92,7 @@ fn test_erc721() -> anyhow::Result<()> { let gas_used = 58_418.into(); let contract_code = [contract_bytecode(), vec![]] - .map(|v| (keccak(v.clone()), v)) + .map(|v| (Either::Left(keccak(v.clone())), v)) .into(); let logs = vec![LogRlp { @@ -139,13 +144,13 @@ fn test_erc721() -> anyhow::Result<()> { beacon_roots_contract_from_storage(&beacon_roots_account_storage); let owner_account = owner_account(); - let owner_account_after = AccountRlp { + let owner_account_after = MptAccountRlp { nonce: owner_account.nonce + 1, balance: owner_account.balance - gas_used * 0xa, ..owner_account }; state_trie_after.insert(owner_nibbles, rlp::encode(&owner_account_after).to_vec())?; - let contract_account_after = AccountRlp { + let contract_account_after = MptAccountRlp { storage_root: contract_storage_after()?.hash(), ..contract_account()? }; @@ -272,8 +277,8 @@ fn contract_storage_after() -> anyhow::Result { ]) } -fn owner_account() -> AccountRlp { - AccountRlp { +fn owner_account() -> MptAccountRlp { + MptAccountRlp { nonce: 2.into(), balance: 0x1000000.into(), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -281,8 +286,8 @@ fn owner_account() -> AccountRlp { } } -fn contract_account() -> anyhow::Result { - Ok(AccountRlp { +fn contract_account() -> anyhow::Result { + Ok(MptAccountRlp { nonce: 0.into(), balance: 0.into(), storage_root: contract_storage()?.hash(), @@ -314,3 +319,19 @@ fn add_to_bloom(bloom: &mut [u8; 256], bloom_entry: &[u8]) { bloom[byte_index as usize] |= bit_value; } } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/global_exit_root.rs b/evm_arithmetization/tests/global_exit_root.rs index 3aa4cc601..3466852ae 100644 --- a/evm_arithmetization/tests/global_exit_root.rs +++ b/evm_arithmetization/tests/global_exit_root.rs @@ -1,8 +1,9 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::time::Duration; +use either::Either; use ethereum_types::H256; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; @@ -13,6 +14,8 @@ use evm_arithmetization::testing_utils::{ ADDRESS_SCALABLE_L2_ADDRESS_HASHED, GLOBAL_EXIT_ROOT_ACCOUNT, GLOBAL_EXIT_ROOT_ADDRESS_HASHED, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use keccak_hash::keccak; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; @@ -59,7 +62,7 @@ fn test_global_exit_root() -> anyhow::Result<()> { let receipts_trie = HashedPartialTrie::from(Node::Empty); let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); + contract_code.insert(Either::Left(keccak(vec![])), vec![]); let ger_data = Some((H256::random(), H256::random())); @@ -90,6 +93,7 @@ fn test_global_exit_root() -> anyhow::Result<()> { receipts_root: receipts_trie.hash(), }; + let state_trie_before = get_state_world(state_trie_before, storage_tries); let inputs = GenerationInputs:: { signed_txns: vec![], burn_addr: None, @@ -99,7 +103,7 @@ fn test_global_exit_root() -> anyhow::Result<()> { state_trie: state_trie_before, transactions_trie, receipts_trie, - storage_tries, + // storage_tries, }, trie_roots_after, contract_code, @@ -130,3 +134,19 @@ fn test_global_exit_root() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 4d446b3c7..0efe66f0e 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -1,15 +1,16 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; use std::time::Duration; use bytes::Bytes; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::generation::mpt::transaction_testing::{ AddressOption, LegacyTransactionRlp, }; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -18,6 +19,8 @@ use evm_arithmetization::testing_utils::{ preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -72,20 +75,20 @@ fn test_log_opcodes() -> anyhow::Result<()> { let code_hash = keccak(code); // Set accounts before the transaction. - let beneficiary_account_before = AccountRlp { + let beneficiary_account_before = MptAccountRlp { nonce: 1.into(), - ..AccountRlp::default() + ..MptAccountRlp::default() }; let sender_balance_before = 5000000000000000u64; - let sender_account_before = AccountRlp { + let sender_account_before = MptAccountRlp { balance: sender_balance_before.into(), - ..AccountRlp::default() + ..MptAccountRlp::default() }; - let to_account_before = AccountRlp { + let to_account_before = MptAccountRlp { balance: 9000000000u64.into(), code_hash, - ..AccountRlp::default() + ..MptAccountRlp::default() }; // Initialize the state trie with three accounts. @@ -129,11 +132,12 @@ fn test_log_opcodes() -> anyhow::Result<()> { rlp::encode(&receipt_0).to_vec(), )?; + let state_trie_before = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie: state_trie_before, transactions_trie: Node::Empty.into(), receipts_trie: receipts_trie.clone(), - storage_tries, + // storage_tries, }; // Prove a transaction which carries out two LOG opcodes. @@ -153,8 +157,8 @@ fn test_log_opcodes() -> anyhow::Result<()> { }; let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); - contract_code.insert(code_hash, code.to_vec()); + contract_code.insert(Either::Left(keccak(vec![])), vec![]); + contract_code.insert(Either::Left(code_hash), code.to_vec()); // Update the state and receipt tries after the transaction, so that we have the // correct expected tries: Update accounts @@ -165,21 +169,21 @@ fn test_log_opcodes() -> anyhow::Result<()> { ..AccountRlp::default() }; #[cfg(feature = "eth_mainnet")] - let beneficiary_account_after = AccountRlp { + let beneficiary_account_after = MptAccountRlp { nonce: 1.into(), - ..AccountRlp::default() + ..MptAccountRlp::default() }; let sender_balance_after = sender_balance_before - gas_used * txn_gas_price; - let sender_account_after = AccountRlp { + let sender_account_after = MptAccountRlp { balance: sender_balance_after.into(), nonce: 1.into(), - ..AccountRlp::default() + ..MptAccountRlp::default() }; - let to_account_after = AccountRlp { + let to_account_after = MptAccountRlp { balance: 9000000000u64.into(), code_hash, - ..AccountRlp::default() + ..MptAccountRlp::default() }; update_beacon_roots_account_storage( @@ -399,3 +403,19 @@ fn test_txn_and_receipt_trie_hash() -> anyhow::Result<()> { Ok(()) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index f97dd41cd..ea5668079 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -1,10 +1,12 @@ #![cfg(feature = "eth_mainnet")] +use std::collections::BTreeMap; use std::str::FromStr; use std::time::Duration; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -13,6 +15,8 @@ use evm_arithmetization::testing_utils::{ preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -46,7 +50,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { 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 { + let sender_account_before = MptAccountRlp { nonce: 5.into(), balance: eth_to_wei(100_000.into()), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -56,7 +60,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { 0x32, // ORIGIN 0xFF, // SELFDESTRUCT ]; - let to_account_before = AccountRlp { + let to_account_before = MptAccountRlp { nonce: 12.into(), balance: eth_to_wei(10_000.into()), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -68,11 +72,12 @@ fn test_selfdestruct() -> anyhow::Result<()> { state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; + let state_trie_before = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie: state_trie_before, transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), - storage_tries, + // storage_tries, }; // Generated using a little py-evm script. @@ -91,7 +96,11 @@ fn test_selfdestruct() -> anyhow::Result<()> { ..Default::default() }; - let contract_code = [(keccak(&code), code.clone()), (keccak([]), vec![])].into(); + let contract_code = [ + (Either::Left(keccak(&code)), code.clone()), + (Either::Left(keccak([])), vec![]), + ] + .into(); let expected_state_trie_after: HashedPartialTrie = { let mut state_trie_after = HashedPartialTrie::from(Node::Empty); @@ -104,7 +113,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - let sender_account_after = AccountRlp { + let sender_account_after = MptAccountRlp { nonce: 6.into(), balance: eth_to_wei(110_000.into()) - 26_002 * 0xa, storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -114,7 +123,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { // EIP-6780: The account won't be deleted because it wasn't created during this // transaction. - let to_account_before = AccountRlp { + let to_account_before = MptAccountRlp { nonce: 12.into(), balance: 0.into(), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -188,3 +197,19 @@ fn test_selfdestruct() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index a1e7fb655..fc2d483e2 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -1,11 +1,12 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; use std::time::Duration; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; +use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -14,6 +15,8 @@ use evm_arithmetization::testing_utils::{ preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -47,23 +50,24 @@ fn test_simple_transfer() -> anyhow::Result<()> { 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 { + let sender_account_before = MptAccountRlp { 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 to_account_before = MptAccountRlp::default(); let (mut state_trie_before, storage_tries) = preinitialized_state_and_storage_tries()?; let mut beacon_roots_account_storage = storage_tries[0].1.clone(); state_trie_before.insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec())?; + let state_trie_before = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie: state_trie_before, transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), - storage_tries, + // storage_tries, }; // Generated using a little py-evm script. @@ -84,7 +88,7 @@ fn test_simple_transfer() -> anyhow::Result<()> { }; let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); + contract_code.insert(Either::Left(keccak(vec![])), vec![]); let expected_state_trie_after: HashedPartialTrie = { let mut state_trie_after = HashedPartialTrie::from(Node::Empty); @@ -100,12 +104,12 @@ fn test_simple_transfer() -> anyhow::Result<()> { let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - let sender_account_after = AccountRlp { + let sender_account_after = MptAccountRlp { balance: sender_account_before.balance - value - gas_used * 10, nonce: sender_account_before.nonce + 1, ..sender_account_before }; - let to_account_after = AccountRlp { + let to_account_after = MptAccountRlp { balance: value, ..to_account_before }; @@ -180,3 +184,19 @@ fn test_simple_transfer() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/two_to_one_block.rs b/evm_arithmetization/tests/two_to_one_block.rs index e808a33e4..98beeb69e 100644 --- a/evm_arithmetization/tests/two_to_one_block.rs +++ b/evm_arithmetization/tests/two_to_one_block.rs @@ -1,5 +1,8 @@ #![cfg(feature = "eth_mainnet")] +use std::collections::BTreeMap; + +use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::fixed_recursive_verifier::{ extract_block_final_public_values, extract_two_to_one_block_hash, @@ -12,6 +15,8 @@ use evm_arithmetization::testing_utils::{ beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllRecursiveCircuits, AllStark, Node, StarkConfig}; use hex_literal::hex; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; @@ -65,9 +70,11 @@ fn dummy_payload(timestamp: u64, is_first_payload: bool) -> anyhow::Result anyhow::Result<()> { Ok(()) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index 01b48c0c6..58a4e1d72 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -1,10 +1,11 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::time::Duration; +use either::Either; use ethereum_types::{H160, H256, U256}; -use evm_arithmetization::generation::mpt::AccountRlp; +use evm_arithmetization::generation::mpt::{AccountRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -13,6 +14,8 @@ use evm_arithmetization::testing_utils::{ preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; use evm_arithmetization::verifier::testing::verify_all_proofs; +use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; +use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use keccak_hash::keccak; use mpt_trie::nibbles::Nibbles; @@ -46,7 +49,7 @@ fn test_withdrawals() -> anyhow::Result<()> { let receipts_trie = HashedPartialTrie::from(Node::Empty); let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); + contract_code.insert(Either::Left(keccak(vec![])), vec![]); // Just one withdrawal. let withdrawals = vec![(H160(random()), U256(random()))]; @@ -63,9 +66,9 @@ fn test_withdrawals() -> anyhow::Result<()> { let addr_state_key = keccak(withdrawals[0].0); let addr_nibbles = Nibbles::from_bytes_be(addr_state_key.as_bytes()).unwrap(); - let account = AccountRlp { + let account = MptAccountRlp { balance: withdrawals[0].1, - ..AccountRlp::default() + ..MptAccountRlp::default() }; trie.insert(addr_nibbles, rlp::encode(&account).to_vec())?; trie.insert( @@ -82,6 +85,7 @@ fn test_withdrawals() -> anyhow::Result<()> { receipts_root: receipts_trie.hash(), }; + let state_trie_before = get_state_world(state_trie_before, storage_tries); let inputs = GenerationInputs:: { signed_txns: vec![], burn_addr: None, @@ -91,7 +95,7 @@ fn test_withdrawals() -> anyhow::Result<()> { state_trie: state_trie_before, transactions_trie, receipts_trie, - storage_tries, + // storage_tries, }, trie_roots_after, contract_code, @@ -123,3 +127,19 @@ fn test_withdrawals() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } + +fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} From 5112c950431ff44b675b93b46f9a544f3e18079e Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 4 Nov 2024 09:49:37 +0100 Subject: [PATCH 40/60] Missing changes in latest commit --- smt_trie/src/code.rs | 3 +- smt_trie/src/smt.rs | 9 ++-- trace_decoder/src/core.rs | 44 ++++++++++--------- trace_decoder/src/interface.rs | 8 ++-- trace_decoder/src/observer.rs | 2 +- trace_decoder/tests/consistent-with-header.rs | 20 ++++++++- zero/Cargo.toml | 2 +- zero/src/trie_diff/mod.rs | 4 +- 8 files changed, 57 insertions(+), 35 deletions(-) diff --git a/smt_trie/src/code.rs b/smt_trie/src/code.rs index 1cc0e4bcb..49e3f6ffe 100644 --- a/smt_trie/src/code.rs +++ b/smt_trie/src/code.rs @@ -11,7 +11,8 @@ pub fn hash_contract_bytecode(mut code: Vec) -> HashOut { poseidon_pad_byte_vec(&mut code); // println!("code bytes = {:?}", code); - // println!("hash = {:?}", hashout2u(poseidon_hash_padded_byte_vec(code.clone()))); + // println!("hash = {:?}", + // hashout2u(poseidon_hash_padded_byte_vec(code.clone()))); poseidon_hash_padded_byte_vec(code) } diff --git a/smt_trie/src/smt.rs b/smt_trie/src/smt.rs index 5e4a83d6e..136b4094b 100644 --- a/smt_trie/src/smt.rs +++ b/smt_trie/src/smt.rs @@ -6,6 +6,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::{Display, Formatter}; use ethereum_types::{H256, U256}; +use mpt_trie::partial_trie::HashedPartialTrie; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::{Field, PrimeField64}; use plonky2::hash::poseidon::{Poseidon, PoseidonHash}; @@ -17,7 +18,6 @@ use crate::db::{Db, MemoryDb}; use crate::utils::{ f2limbs, get_unique_sibling, hash0, hash_key_hash, hashout2u, key2u, limbs2f, u2h, u2k, }; -use mpt_trie::partial_trie::HashedPartialTrie; pub(crate) const HASH_TYPE: u8 = 0; pub(crate) const INTERNAL_TYPE: u8 = 1; @@ -521,7 +521,8 @@ fn serialize( let index = v.len(); v.push(HASH_TYPE.into()); v.push(key2u(key)); - if index == 0 { // Empty hash node is at the beggining of the segment + if index == 0 { + // Empty hash node is at the beggining of the segment index } else { index + offset @@ -558,7 +559,7 @@ fn serialize( keys_to_include, offset, ) - .into(); + .into(); v[index + 1] = i_left; let i_right = serialize( smt, @@ -568,7 +569,7 @@ fn serialize( keys_to_include, offset, ) - .into(); + .into(); v[index + 2] = i_right; index + offset } diff --git a/trace_decoder/src/core.rs b/trace_decoder/src/core.rs index 8093098c1..aa86c21af 100644 --- a/trace_decoder/src/core.rs +++ b/trace_decoder/src/core.rs @@ -10,21 +10,22 @@ use ethereum_types::{Address, BigEndianHash as _, U256}; use evm_arithmetization::{ generation::TrieInputs, proof::{BlockMetadata, TrieRoots}, + world::{ + tries::{MptKey, ReceiptTrie, StateMpt, StorageTrie, TransactionTrie}, + type1, type2, + world::{StateWorld, Type1World, Type2World, World}, + }, GenerationInputs, }; use itertools::Itertools as _; use keccak_hash::H256; use mpt_trie::partial_trie::PartialTrie as _; use nunny::NonEmpty; +use smt_trie::code::hash_bytecode_u256; use zk_evm_common::gwei_to_wei; +use crate::observer::{DummyObserver, Observer}; use crate::{ - observer::{DummyObserver, Observer}, - world::Type2World, -}; -use crate::{ - tries::{MptKey, ReceiptTrie, StateMpt, StorageTrie, TransactionTrie}, - world::{Type1World, World}, BlockLevelData, BlockTrace, BlockTraceTriePreImages, CombinedPreImages, ContractCodeUsage, OtherBlockData, SeparateStorageTriesPreImage, SeparateTriePreImage, SeparateTriePreImages, TxnInfo, TxnMeta, TxnTrace, @@ -133,9 +134,17 @@ pub fn entrypoint( after, withdrawals, }| { - let (state, storage) = world - .expect_left("TODO(0xaatif): evm_arithemetization accepts an SMT") - .into_state_and_storage(); + let contract_code_hash = |it: &[u8]| { + if let Either::Right(_type2world) = &world { + Either::Right(hash_bytecode_u256(it.to_vec())) + } else { + Either::Left(keccak_hash::keccak(&it)) + } + }; + let contract_code = contract_code + .into_iter() + .map(|it| (contract_code_hash(&it), it)) + .collect(); GenerationInputs { txn_number_before: first_txn_ix.into(), gas_used_before: running_gas_used.into(), @@ -147,18 +156,14 @@ pub fn entrypoint( withdrawals, ger_data, tries: TrieInputs { - state_trie: state.into(), + state_trie: StateWorld { state: world }, transactions_trie: transaction.into(), receipts_trie: receipt.into(), - storage_tries: storage.into_iter().map(|(k, v)| (k, v.into())).collect(), }, trie_roots_after: after, checkpoint_state_trie_root, checkpoint_consolidated_hash, - contract_code: contract_code - .into_iter() - .map(|it| (keccak_hash::keccak(&it), it)) - .collect(), + contract_code, block_metadata: b_meta.clone(), block_hashes: b_hashes.clone(), burn_addr, @@ -230,23 +235,22 @@ fn start( ) } BlockTraceTriePreImages::Combined(CombinedPreImages { compact }) => { - let instructions = crate::wire::parse(&compact) + let instructions = evm_arithmetization::world::wire::parse(&compact) .context("couldn't parse instructions from binary format")?; match wire_disposition { WireDisposition::Type1 => { - let crate::type1::Frontend { + let type1::Frontend { state, storage, code, - } = crate::type1::frontend(instructions)?; + } = type1::frontend(instructions)?; ( Either::Left(Type1World::new(state, storage)?), Hash2Code::from_iter(code.into_iter().map(NonEmpty::into_vec)), ) } WireDisposition::Type2 => { - let crate::type2::Frontend { world: trie, code } = - crate::type2::frontend(instructions)?; + let type2::Frontend { world: trie, code } = type2::frontend(instructions)?; ( Either::Right(trie), Hash2Code::from_iter(code.into_iter().map(NonEmpty::into_vec)), diff --git a/trace_decoder/src/interface.rs b/trace_decoder/src/interface.rs index abe3b0af0..75c91c52f 100644 --- a/trace_decoder/src/interface.rs +++ b/trace_decoder/src/interface.rs @@ -67,7 +67,7 @@ pub enum SeparateTriePreImage { #[serde(rename_all = "snake_case")] pub struct CombinedPreImages { /// Compact combined state and storage tries. - #[serde(with = "crate::hex")] + #[serde(with = "evm_arithmetization::world::hex")] pub compact: Vec, } @@ -100,13 +100,13 @@ pub struct TxnMeta { /// Txn byte code. This is also the raw RLP bytestring inserted into the txn /// trie by this txn. Note that the key is not included and this is only /// the rlped value of the node! - #[serde(with = "crate::hex")] + #[serde(with = "evm_arithmetization::world::hex")] pub byte_code: Vec, /// Rlped bytes of the new receipt value inserted into the receipt trie by /// this txn. Note that the key is not included and this is only the rlped /// value of the node! - #[serde(with = "crate::hex")] + #[serde(with = "evm_arithmetization::world::hex")] pub new_receipt_trie_node_byte: Vec, /// Gas used by this txn (Note: not cumulative gas used). @@ -160,7 +160,7 @@ pub enum ContractCodeUsage { /// Contract was created (and these are the bytes). Note that this new /// contract code will not appear in the [`BlockTrace`] map. - Write(#[serde(with = "crate::hex")] Vec), + Write(#[serde(with = "evm_arithmetization::world::hex")] Vec), } /// Other data that is needed for proof gen. diff --git a/trace_decoder/src/observer.rs b/trace_decoder/src/observer.rs index 428cac086..05d21d7ee 100644 --- a/trace_decoder/src/observer.rs +++ b/trace_decoder/src/observer.rs @@ -1,9 +1,9 @@ use std::marker::PhantomData; use ethereum_types::U256; +use evm_arithmetization::world::tries::{ReceiptTrie, TransactionTrie}; use crate::core::IntraBlockTries; -use crate::tries::{ReceiptTrie, TransactionTrie}; /// Observer API for the trace decoder. /// Observer is used to collect various debugging and metadata info diff --git a/trace_decoder/tests/consistent-with-header.rs b/trace_decoder/tests/consistent-with-header.rs index 63df41b4f..9ff9d990b 100644 --- a/trace_decoder/tests/consistent-with-header.rs +++ b/trace_decoder/tests/consistent-with-header.rs @@ -7,9 +7,13 @@ mod common; use alloy_compat::Compat as _; use assert2::check; use common::{cases, Case}; +use either::Either; +use ethereum_types::BigEndianHash; use itertools::Itertools; +use keccak_hash::H256; use libtest_mimic::{Arguments, Trial}; use mpt_trie::partial_trie::PartialTrie as _; +use smt_trie::utils::hashout2u; use trace_decoder::observer::DummyObserver; use zero::prover::WIRE_DISPOSITION; @@ -36,12 +40,24 @@ fn main() -> anyhow::Result<()> { check!(gen_inputs.len() >= 2); check!( Some(other.checkpoint_state_trie_root) - == gen_inputs.first().map(|it| it.tries.state_trie.hash()) + == gen_inputs + .first() + .map(|it| match &it.tries.state_trie.state { + Either::Left(type1world) => type1world.state_trie().hash(), + Either::Right(type2world) => + H256::from_uint(&hashout2u(type2world.as_smt().root)), + }) ); let pairs = || gen_inputs.iter().tuple_windows::<(_, _)>(); check!( pairs().position(|(before, after)| { - before.trie_roots_after.state_root != after.tries.state_trie.hash() + let after_hash = match &after.tries.state_trie.state { + Either::Left(type1world) => type1world.state_trie().hash(), + Either::Right(type2world) => { + H256::from_uint(&hashout2u(type2world.as_smt().root)) + } + }; + before.trie_roots_after.state_root != after_hash }) == None ); check!( diff --git a/zero/Cargo.toml b/zero/Cargo.toml index fa1c464b6..88c8c580b 100644 --- a/zero/Cargo.toml +++ b/zero/Cargo.toml @@ -60,7 +60,7 @@ mockall = "0.13.0" [features] -default = ["cdk_erigon"] +default = ["eth_mainnet"] eth_mainnet = ["evm_arithmetization/eth_mainnet", "trace_decoder/eth_mainnet"] cdk_erigon = ["evm_arithmetization/cdk_erigon", "trace_decoder/cdk_erigon"] polygon_pos = ["evm_arithmetization/polygon_pos", "trace_decoder/polygon_pos"] diff --git a/zero/src/trie_diff/mod.rs b/zero/src/trie_diff/mod.rs index 088e2d835..8a5f7df3a 100644 --- a/zero/src/trie_diff/mod.rs +++ b/zero/src/trie_diff/mod.rs @@ -1,4 +1,4 @@ -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::DebugOutputTries; use mpt_trie::debug_tools::diff::{create_full_diff_between_tries, DiffPoint}; use mpt_trie::utils::TrieNodeType; @@ -85,7 +85,7 @@ pub fn compare_tries( } let state_trie_diff = create_full_diff_between_tries(&left.state_trie, &right.state_trie); - compare_tries_and_output_results::( + compare_tries_and_output_results::( "state trie", state_trie_diff.diff_points, block_number, From 2c2d137d86cdcdd521d2cf08fc0f64256cc2cb9d Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 4 Nov 2024 15:01:53 +0100 Subject: [PATCH 41/60] Fix unit test compilation errors --- .../benches/fibonacci_25m_gas.rs | 121 +++++--- .../src/cpu/kernel/constants/mod.rs | 1 - .../src/cpu/kernel/interpreter.rs | 1 - .../src/cpu/kernel/tests/account_code.rs | 173 +++++++---- .../src/cpu/kernel/tests/add11.rs | 273 +++++++++++++----- .../src/cpu/kernel/tests/balance.rs | 57 ++-- .../src/cpu/kernel/tests/mod.rs | 34 +++ .../src/cpu/kernel/tests/mpt/delete.rs | 16 +- .../src/cpu/kernel/tests/mpt/hash.rs | 55 ++-- .../src/cpu/kernel/tests/mpt/insert.rs | 23 +- .../src/cpu/kernel/tests/mpt/load.rs | 62 +++- .../src/cpu/kernel/tests/mpt/mod.rs | 91 +++--- .../src/cpu/kernel/tests/mpt/read.rs | 8 +- .../transaction_parsing/parse_type_3_txn.rs | 27 +- evm_arithmetization/src/generation/mod.rs | 3 +- evm_arithmetization/src/generation/mpt.rs | 60 +++- .../src/generation/prover_input.rs | 8 +- evm_arithmetization/src/generation/state.rs | 6 +- .../src/generation/trie_extractor.rs | 2 +- evm_arithmetization/tests/add11_yml.rs | 2 +- evm_arithmetization/tests/erc20.rs | 2 +- evm_arithmetization/tests/erc721.rs | 2 +- evm_arithmetization/tests/log_opcode.rs | 2 +- evm_arithmetization/tests/selfdestruct.rs | 2 +- evm_arithmetization/tests/simple_transfer.rs | 2 +- evm_arithmetization/tests/withdrawals.rs | 2 +- 26 files changed, 722 insertions(+), 313 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 96d264530..a68713bcb 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -10,14 +10,12 @@ use std::str::FromStr; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use either::Either; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; -use ethereum_types::{Address, H256, U256}; -#[cfg(feature = "cdk_erigon")] -use ethereum_types::{BigEndianHash, H160}; +use ethereum_types::{Address, BigEndianHash, H256, U256}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; use evm_arithmetization::generation::mpt::{ - get_h256_from_code_hash, get_u256_from_code_hash, AccountRlp, CodeHashType, LegacyReceiptRlp, - MptAccountRlp, + get_h256_from_code_hash, get_u256_from_code_hash, AccountRlp, CodeHashType, EitherRlp, + LegacyReceiptRlp, MptAccountRlp, }; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; @@ -39,9 +37,10 @@ use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::types::Field; #[cfg(feature = "cdk_erigon")] use plonky2::field::types::PrimeField64; +use smt_trie::code::hash_bytecode_u256; +use smt_trie::utils::hashout2u; #[cfg(feature = "cdk_erigon")] use smt_trie::{ - code::hash_bytecode_u256, keys::{key_balance, key_code_length}, utils::hashout2u, }; @@ -133,21 +132,25 @@ fn prepare_setup() -> anyhow::Result> { }; let to_account_before = if cfg!(feature = "cdk_erigon") { - Either::Right(SmtAccountRlp { - nonce: 1.into(), - balance: 0.into(), - code_hash: get_u256_from_code_hash(code_hash.clone()) - .expect("In cdk_erigon, the code_hash is a U256"), - code_length: code.len().into(), - }) + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: 1.into(), + balance: 0.into(), + code_hash: get_u256_from_code_hash(code_hash.clone()) + .expect("In cdk_erigon, the code_hash is a U256"), + code_length: code.len().into(), + }), + } } else { - Either::Left(MptAccountRlp { - nonce: 1.into(), - balance: 0.into(), - storage_root: empty_trie_root, - code_hash: get_h256_from_code_hash(code_hash.clone()) - .expect("In eth_mainnet, the code_hash is a H256"), - }) + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + balance: 0.into(), + storage_root: empty_trie_root, + code_hash: get_h256_from_code_hash(code_hash.clone()) + .expect("In eth_mainnet, the code_hash is a H256"), + }), + } }; // #[cfg(feature = "cdk_erigon")] @@ -187,21 +190,24 @@ fn prepare_setup() -> anyhow::Result> { let mut state_trie_before = StateWorld::default(); #[cfg(feature = "eth_mainnet")] - let (mut state_trie_before, mut storage_tries) = preinitialized_state_and_storage_tries()?; + let (mut state_trie_before_hashed, mut storage_tries) = + preinitialized_state_and_storage_tries()?; #[cfg(feature = "eth_mainnet")] let mut beacon_roots_account_storage = storage_tries[0].1.clone(); #[cfg(feature = "eth_mainnet")] { let sender_account_before_mpt = sender_account_before.expect_left("The sender account is an MPT."); - state_trie_before.insert( + state_trie_before_hashed.insert( sender_nibbles, - rlp::encode(&sender_account_before_mpy).to_vec(), + rlp::encode(&sender_account_before_mpt).to_vec(), )?; - state_trie_before.insert(to_nibbles, rlp::encode(&to_account_before).to_vec())?; + state_trie_before_hashed.insert(to_nibbles, to_account_before.rlp_encode().to_vec())?; storage_tries.push((sender_state_key, Node::Empty.into())); storage_tries.push((to_state_key, Node::Empty.into())); + state_trie_before = + get_state_world_from_trie_and_storage(state_trie_before_hashed, storage_tries); } #[cfg(feature = "cdk_erigon")] @@ -282,34 +288,39 @@ fn prepare_setup() -> anyhow::Result> { let sender_account_after = if cfg!(feature = "cdk_erigon") { let sender_account_before_smt = sender_account_before.expect_right("cdk_erigon expects SMTs."); - Either::Right(SmtAccountRlp { - balance: sender_account_before_smt.get_balance() - - value - - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before_smt.get_nonce() + 1, - ..sender_account_before_smt - }) + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: sender_account_before_smt.get_balance() + - value + - gas_used * block_metadata.block_base_fee, + nonce: sender_account_before_smt.get_nonce() + 1, + ..sender_account_before_smt + }), + } } else { let sender_account_before_mpt = sender_account_before.expect_left("eth_mainnet expects MPTs."); - Either::Left(MptAccountRlp { - balance: sender_account_before_mpt.get_balance() - - value - - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before_mpt.get_nonce() + 1, - ..sender_account_before_mpt - }) + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: sender_account_before_mpt.get_balance() + - value + - gas_used * block_metadata.block_base_fee, + nonce: sender_account_before_mpt.get_nonce() + 1, + ..sender_account_before_mpt + }), + } }; let to_account_after = &to_account_before; let mut expected_state_trie_after = StateWorld::default(); #[cfg(feature = "eth_mainnet")] - let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); + let mut expected_state_trie_after_hashed = HashedPartialTrie::from(Node::Empty); #[cfg(feature = "eth_mainnet")] { - expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; - expected_state_trie_after.insert(to_nibbles, rlp::encode(&to_account_after).to_vec())?; + expected_state_trie_after_hashed + .insert(sender_nibbles, sender_account_after.rlp_encode().to_vec())?; + expected_state_trie_after_hashed + .insert(to_nibbles, to_account_after.rlp_encode().to_vec())?; update_beacon_roots_account_storage( &mut beacon_roots_account_storage, @@ -318,10 +329,12 @@ fn prepare_setup() -> anyhow::Result> { )?; let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - expected_state_trie_after.insert( + expected_state_trie_after_hashed.insert( beacon_roots_account_nibbles(), rlp::encode(&beacon_roots_account).to_vec(), )?; + expected_state_trie_after = + get_state_world_from_trie_and_storage(expected_state_trie_after_hashed, vec![]); } #[cfg(feature = "cdk_erigon")] @@ -445,3 +458,25 @@ fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, c // smt.set(key_storage(addr, k), v); // } } +use std::collections::BTreeMap; + +use evm_arithmetization::world::tries::StateMpt; +use evm_arithmetization::world::world::Type1World; +#[cfg(feature = "eth_mainnet")] +fn get_state_world_from_trie_and_storage( + state_trie: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + use evm_arithmetization::world::tries::StorageTrie; + + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index e4a107050..21a88e0a4 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -9,7 +9,6 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::journal_entry::JournalEntry; use crate::cpu::kernel::constants::trie_type::PartialTrieType; use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField; -use crate::generation::mpt::AccountRlp; use crate::memory::segments::Segment; pub(crate) mod context_metadata; diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 760ed0dbc..2b5f4ec48 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -8,7 +8,6 @@ use std::collections::{BTreeSet, HashMap}; use anyhow::anyhow; -use either::Either; use ethereum_types::{BigEndianHash, U256}; use log::Level; use mpt_trie::partial_trie::PartialTrie; diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index d6bf0f004..667d10d72 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -10,8 +10,8 @@ use mpt_trie::partial_trie::{HashedPartialTrie, Node, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::hash::hash_types::RichField; use rand::{thread_rng, Rng}; -#[cfg(feature = "cdk_erigon")] -use smt_trie::{code::hash_bytecode_u256, smt::Smt, utils::hashout2u}; +// #[cfg(feature = "cdk_erigon")] +use smt_trie::code::hash_bytecode_u256; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata::{self, GasLimit}; @@ -20,8 +20,8 @@ use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; #[cfg(feature = "eth_mainnet")] -use crate::generation::mpt::{load_linked_lists_and_txn_and_receipt_mpts, load_state_mpt}; -use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; +use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; +use crate::generation::mpt::{AccountRlp, EitherRlp, MptAccountRlp, SmtAccountRlp}; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -142,11 +142,11 @@ pub(crate) fn initialize_mpts( (initial_storage_len_addr, storage_len.into()), ]); - let state_addr = + let _state_addr = MemoryAddress::new_bundle((GlobalMetadata::StateTrieRoot as usize).into()).unwrap(); - let txn_addr = + let _txn_addr = MemoryAddress::new_bundle((GlobalMetadata::TransactionTrieRoot as usize).into()).unwrap(); - let receipts_addr = + let _receipts_addr = MemoryAddress::new_bundle((GlobalMetadata::ReceiptTrieRoot as usize).into()).unwrap(); } @@ -155,7 +155,7 @@ pub(crate) fn initialize_mpts( pub(crate) fn prepare_interpreter( interpreter: &mut Interpreter, address: Address, - account: Box, + account: &EitherRlp, ) -> Result<()> { let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; @@ -269,28 +269,52 @@ pub(crate) fn prepare_interpreter( Ok(()) } -// Test account with a given code hash. -#[cfg(feature = "eth_mainnet")] -fn test_account(code: &[u8]) -> MptAccountRlp { - MptAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: keccak(code), - } -} +// // Test account with a given code hash. +// #[cfg(feature = "eth_mainnet")] +// fn test_account(code: &[u8]) -> MptAccountRlp { +// MptAccountRlp { +// nonce: U256::from(1111), +// balance: U256::from(2222), +// storage_root: HashedPartialTrie::from(Node::Empty).hash(), +// code_hash: keccak(code), +// } +// } // Test account with a given code hash. -#[cfg(feature = "cdk_erigon")] -fn test_account(code: &[u8]) -> SmtAccountRlp { - SmtAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - code_hash: hash_bytecode_u256(code.to_vec()), - code_length: code.len().into(), +// #[cfg(feature = "eth_mainnet")] +fn test_account(code: &[u8]) -> EitherRlp { + if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: HashedPartialTrie::from(Node::Empty).hash(), + code_hash: keccak(code), + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: hash_bytecode_u256(code.to_vec()), + code_length: code.len().into(), + }), + } } } +// // Test account with a given code hash. +// #[cfg(feature = "cdk_erigon")] +// fn test_account(code: &[u8]) -> SmtAccountRlp { +// SmtAccountRlp { +// nonce: U256::from(1111), +// balance: U256::from(2222), +// code_hash: hash_bytecode_u256(code.to_vec()), +// code_length: code.len().into(), +// } +// } + fn random_code() -> Vec { let mut rng = thread_rng(); let num_bytes = rng.gen_range(0..1000); @@ -300,12 +324,12 @@ fn random_code() -> Vec { #[test] fn test_extcodesize() -> Result<()> { let code = random_code(); - let account = Box::new(test_account(&code)); + let account = test_account(&code); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); let address: Address = thread_rng().gen(); // Prepare the interpreter by inserting the account in the state trie. - prepare_interpreter(&mut interpreter, address, account)?; + prepare_interpreter(&mut interpreter, address, &account)?; let extcodesize = KERNEL.global_labels["extcodesize"]; @@ -352,12 +376,12 @@ fn test_extcodesize() -> Result<()> { #[test] fn test_extcodecopy() -> Result<()> { let code = random_code(); - let account = Box::new(test_account(&code)); + let account = test_account(&code); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); let address: Address = thread_rng().gen(); // Prepare the interpreter by inserting the account in the state trie. - prepare_interpreter(&mut interpreter, address, account)?; + prepare_interpreter(&mut interpreter, address, &account)?; let context = interpreter.context(); interpreter.generation_state.memory.contexts[context].segments @@ -538,21 +562,24 @@ fn sstore() -> Result<()> { let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; let code_hash = keccak(code); - let account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..AccountRlp::default() + let account_before = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..MptAccountRlp::default() + }), }; let mut state_trie_before = HashedPartialTrie::from(Node::Empty); - state_trie_before.insert(addr_nibbles, rlp::encode(&account_before).to_vec())?; + state_trie_before.insert(addr_nibbles, account_before.rlp_encode().to_vec())?; + let state_trie = get_state_world_no_storage(state_trie_before); let trie_inputs = TrieInputs { - state_trie: state_trie_before.clone(), + state_trie, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - storage_tries: vec![(addr_hashed, Node::Empty.into())], + // storage_tries: vec![(addr_hashed, Node::Empty.into())], }; let initial_stack = vec![]; @@ -578,19 +605,21 @@ fn sstore() -> Result<()> { // The code should have added an element to the storage of `to_account`. We run // `mpt_hash_state_trie` to check that. - let account_after = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..AccountRlp::default() + let account_after = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..MptAccountRlp::default() + }), }; let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); - expected_state_trie_after.insert(addr_nibbles, rlp::encode(&account_after).to_vec())?; + expected_state_trie_after.insert(addr_nibbles, account_after.rlp_encode().to_vec())?; let expected_state_trie_hash = expected_state_trie_after.hash(); @@ -619,6 +648,13 @@ fn sstore() -> Result<()> { #[test] #[cfg(feature = "eth_mainnet")] fn sload() -> Result<()> { + use std::collections::BTreeMap; + + use crate::world::{ + tries::{StateMpt, StorageTrie}, + world::Type1World, + }; + let addr = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); let addr_hashed = keccak(addr); @@ -633,21 +669,37 @@ fn sload() -> Result<()> { ]; let code_hash = keccak(code); - let account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..AccountRlp::default() + let account_before = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..MptAccountRlp::default() + }), }; let mut state_trie_before = HashedPartialTrie::from(Node::Empty); - state_trie_before.insert(addr_nibbles, rlp::encode(&account_before).to_vec())?; - + state_trie_before.insert(addr_nibbles, account_before.rlp_encode().to_vec())?; + + let mut type1world = Type1World::new( + StateMpt::new_with_inner(state_trie_before.clone()), + BTreeMap::default(), + ) + .unwrap(); + let storage_tries = vec![(addr_hashed, Node::Empty.into())]; + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + let state_trie = StateWorld { + state: Either::Left(type1world), + }; let trie_inputs = TrieInputs { - state_trie: state_trie_before.clone(), + state_trie, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - storage_tries: vec![(addr_hashed, Node::Empty.into())], + // storage_tries: vec![(addr_hashed, Node::Empty.into())], }; let initial_stack = vec![]; @@ -714,3 +766,16 @@ fn sload() -> Result<()> { assert_eq!(hash, expected_state_trie_hash); Ok(()) } + +#[cfg(feature = "eth_mainnet")] +pub(crate) fn get_state_world_no_storage(state_trie: HashedPartialTrie) -> StateWorld { + use std::collections::BTreeMap; + + use crate::world::{tries::StateMpt, world::Type1World}; + + StateWorld { + state: Either::Left( + Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(), + ), + } +} diff --git a/evm_arithmetization/src/cpu/kernel/tests/add11.rs b/evm_arithmetization/src/cpu/kernel/tests/add11.rs index b6ecf591a..b2228ee5d 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/add11.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/add11.rs @@ -1,8 +1,9 @@ -#![cfg(feature = "eth_mainnet")] +// #![cfg(feature = "eth_mainnet")] use std::collections::HashMap; use std::str::FromStr; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; use hex_literal::hex; use keccak_hash::keccak; @@ -10,10 +11,14 @@ use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::{HashedPartialTrie, Node, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::field::types::Field; +use smt_trie::code::hash_bytecode_u256; +use super::get_state_world_from_trie_and_storage; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; -use crate::generation::mpt::{AccountRlp, LegacyReceiptRlp}; +use crate::generation::mpt::{ + AccountRlp, EitherRlp, LegacyReceiptRlp, MptAccountRlp, SmtAccountRlp, +}; use crate::generation::TrieInputs; use crate::proof::{BlockHashes, BlockMetadata, TrieRoots}; use crate::testing_utils::{ @@ -37,24 +42,66 @@ fn test_add11_yml() { let to_nibbles = Nibbles::from_bytes_be(to_hashed.as_bytes()).unwrap(); let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; - let code_hash = keccak(code); + let code_hash = if cfg!(feature = "eth_mainnet") { + Either::Left(keccak(code)) + } else { + Either::Right(hash_bytecode_u256(code.to_vec())) + }; let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); - contract_code.insert(code_hash, code.to_vec()); + if cfg!(feature = "eth_mainnet") { + contract_code.insert(Either::Left(keccak(vec![])), vec![]); + contract_code.insert(code_hash, code.to_vec()); + } - let beneficiary_account_before = AccountRlp { - nonce: 1.into(), - ..AccountRlp::default() + let beneficiary_account_before = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: 1.into(), + ..SmtAccountRlp::default() + }), + } }; - let sender_account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..AccountRlp::default() + let sender_account_before = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + ..SmtAccountRlp::default() + }), + } }; - let to_account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..AccountRlp::default() + + let to_account_before = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_right("cdk_erigon uses Poseidon."), + code_length: code.len().into(), + ..SmtAccountRlp::default() + }), + } }; let (mut state_trie_before, mut storage_tries) = @@ -63,23 +110,24 @@ fn test_add11_yml() { state_trie_before .insert( beneficiary_nibbles, - rlp::encode(&beneficiary_account_before).to_vec(), + beneficiary_account_before.rlp_encode().to_vec(), ) .unwrap(); state_trie_before - .insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()) + .insert(sender_nibbles, sender_account_before.rlp_encode().to_vec()) .unwrap(); state_trie_before - .insert(to_nibbles, rlp::encode(&to_account_before).to_vec()) + .insert(to_nibbles, to_account_before.rlp_encode().to_vec()) .unwrap(); storage_tries.push((to_hashed, Node::Empty.into())); + let state_trie = get_state_world_from_trie_and_storage(state_trie_before, storage_tries); let tries_before = TrieInputs { - state_trie: state_trie_before, + state_trie, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - storage_tries, + // storage_tries, }; let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16"); @@ -100,26 +148,63 @@ fn test_add11_yml() { }; let expected_state_trie_after = { - let beneficiary_account_after = AccountRlp { - nonce: 1.into(), - ..AccountRlp::default() + let beneficiary_account_after = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: 1.into(), + ..SmtAccountRlp::default() + }), + } }; - let sender_account_after = AccountRlp { - balance: 0xde0b6b3a75be550u64.into(), - nonce: 1.into(), - ..AccountRlp::default() + let sender_account_after = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..SmtAccountRlp::default() + }), + } }; - let to_account_after = AccountRlp { - balance: 0xde0b6b3a76586a0u64.into(), - code_hash, - // Storage map: { 0 => 2 } - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..AccountRlp::default() + + let to_account_after = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), + // Storage map: { 0 => 2 } + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash: code_hash.expect_right("cdk_erigon uses Keccak."), + ..SmtAccountRlp::default() + }), + } }; + update_beacon_roots_account_storage( &mut beacon_roots_account_storage, block_metadata.block_timestamp, @@ -133,19 +218,19 @@ fn test_add11_yml() { expected_state_trie_after .insert( beneficiary_nibbles, - rlp::encode(&beneficiary_account_after).to_vec(), + beneficiary_account_after.rlp_encode().to_vec(), ) .unwrap(); expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()) + .insert(sender_nibbles, sender_account_after.rlp_encode().to_vec()) .unwrap(); expected_state_trie_after - .insert(to_nibbles, rlp::encode(&to_account_after).to_vec()) + .insert(to_nibbles, to_account_after.rlp_encode().to_vec()) .unwrap(); expected_state_trie_after .insert( beacon_roots_account_nibbles(), - rlp::encode(&beacon_roots_account).to_vec(), + beacon_roots_account.rlp_encode().to_vec(), ) .unwrap(); expected_state_trie_after @@ -221,24 +306,65 @@ fn test_add11_yml_with_exception() { let to_nibbles = Nibbles::from_bytes_be(to_hashed.as_bytes()).unwrap(); let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x8e, 0x00]; - let code_hash = keccak(code); + let code_hash = if cfg!(feature = "eth_mainnet") { + Either::Left(keccak(code)) + } else { + Either::Right(hash_bytecode_u256(code.to_vec())) + }; let mut contract_code = HashMap::new(); - contract_code.insert(keccak(vec![]), vec![]); - contract_code.insert(code_hash, code.to_vec()); + if cfg!(feature = "eth_mainnet") { + contract_code.insert(Either::Left(keccak(vec![])), vec![]); + contract_code.insert(code_hash, code.to_vec()); + } - let beneficiary_account_before = AccountRlp { - nonce: 1.into(), - ..AccountRlp::default() + let beneficiary_account_before = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: 1.into(), + ..SmtAccountRlp::default() + }), + } }; - let sender_account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..AccountRlp::default() + let sender_account_before = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + ..SmtAccountRlp::default() + }), + } }; - let to_account_before = AccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..AccountRlp::default() + let to_account_before = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_right("cdk_erigon uses Poseidon."), + code_length: code.len().into(), + ..SmtAccountRlp::default() + }), + } }; let (mut state_trie_before, mut storage_tries) = @@ -247,23 +373,25 @@ fn test_add11_yml_with_exception() { state_trie_before .insert( beneficiary_nibbles, - rlp::encode(&beneficiary_account_before).to_vec(), + beneficiary_account_before.rlp_encode().to_vec(), ) .unwrap(); state_trie_before - .insert(sender_nibbles, rlp::encode(&sender_account_before).to_vec()) + .insert(sender_nibbles, sender_account_before.rlp_encode().to_vec()) .unwrap(); state_trie_before - .insert(to_nibbles, rlp::encode(&to_account_before).to_vec()) + .insert(to_nibbles, to_account_before.rlp_encode().to_vec()) .unwrap(); storage_tries.push((to_hashed, Node::Empty.into())); + let state_trie = get_state_world_from_trie_and_storage(state_trie_before, storage_tries); + let tries_before = TrieInputs { - state_trie: state_trie_before, + state_trie, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - storage_tries, + // storage_tries, }; let txn = hex!("f863800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0801ba0ffb600e63115a7362e7811894a91d8ba4330e526f22121c994c4692035dfdfd5a06198379fcac8de3dbfac48b165df4bf88e2088f294b61efb9a65fe2281c76e16"); @@ -289,11 +417,24 @@ fn test_add11_yml_with_exception() { let expected_state_trie_after = { let beneficiary_account_after = beneficiary_account_before; // This is the only account that changes: the nonce and the balance are updated. - let sender_account_after = AccountRlp { - balance: sender_account_before.balance - txn_gas_limit * gas_price, - nonce: 1.into(), - ..AccountRlp::default() + let sender_account_after = if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + balance: sender_account_before.get_balance() - txn_gas_limit * gas_price, + nonce: 1.into(), + ..MptAccountRlp::default() + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + balance: sender_account_before.get_balance() - txn_gas_limit * gas_price, + nonce: 1.into(), + ..SmtAccountRlp::default() + }), + } }; + let to_account_after = to_account_before; update_beacon_roots_account_storage( @@ -309,14 +450,14 @@ fn test_add11_yml_with_exception() { expected_state_trie_after .insert( beneficiary_nibbles, - rlp::encode(&beneficiary_account_after).to_vec(), + beneficiary_account_after.rlp_encode().to_vec(), ) .unwrap(); expected_state_trie_after - .insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec()) + .insert(sender_nibbles, sender_account_after.rlp_encode().to_vec()) .unwrap(); expected_state_trie_after - .insert(to_nibbles, rlp::encode(&to_account_after).to_vec()) + .insert(to_nibbles, to_account_after.rlp_encode().to_vec()) .unwrap(); expected_state_trie_after .insert( diff --git a/evm_arithmetization/src/cpu/kernel/tests/balance.rs b/evm_arithmetization/src/cpu/kernel/tests/balance.rs index 2f2a84b0d..ec983fd14 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/balance.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/balance.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use either::Either; use ethereum_types::{Address, BigEndianHash, H256, U256}; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; @@ -7,44 +8,58 @@ use rand::{thread_rng, Rng}; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::prepare_interpreter; -use crate::generation::mpt::AccountRlp; +use crate::generation::mpt::EitherRlp; +use crate::generation::mpt::MptAccountRlp; use crate::generation::mpt::SmtAccountRlp; use crate::Node; // Test account with a given code hash. -#[cfg(feature = "eth_mainnet")] -fn test_account(balance: U256) -> AccountRlp { - AccountRlp { - nonce: U256::from(1111), - balance, - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: H256::from_uint(&U256::from(8888)), +// #[cfg(feature = "eth_mainnet")] +fn test_account(balance: U256) -> EitherRlp { + if cfg!(feature = "eth_mainnet") { + EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: U256::from(1111), + balance, + storage_root: HashedPartialTrie::from(Node::Empty).hash(), + code_hash: H256::from_uint(&U256::from(8888)), + }), + } + } else { + EitherRlp { + account_rlp: Either::Right(SmtAccountRlp { + nonce: U256::from(1111), + balance, + code_hash: U256::from(8888), + code_length: 0.into(), + }), + } } } -// Test account with a given code hash. -#[cfg(feature = "cdk_erigon")] -fn test_account(balance: U256) -> SmtAccountRlp { - use smt_trie::code::hash_bytecode_u256; +// // Test account with a given code hash. +// #[cfg(feature = "cdk_erigon")] +// fn test_account(balance: U256) -> SmtAccountRlp { +// use smt_trie::code::hash_bytecode_u256; - SmtAccountRlp { - nonce: U256::from(1111), - balance, - code_hash: hash_bytecode_u256(vec![0x01, 0x00]), - code_length: 2.into(), - } -} +// SmtAccountRlp { +// nonce: U256::from(1111), +// balance, +// code_hash: hash_bytecode_u256(vec![0x01, 0x00]), +// code_length: 2.into(), +// } +// } #[test] fn test_balance() -> Result<()> { let mut rng = thread_rng(); let balance = U256(rng.gen()); - let account = Box::new(test_account(balance)); + let account = test_account(balance); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); let address: Address = rng.gen(); // Prepare the interpreter by inserting the account in the state trie. - prepare_interpreter(&mut interpreter, address, account)?; + prepare_interpreter(&mut interpreter, address, &account)?; // Test `balance` interpreter.generation_state.registers.program_counter = KERNEL.global_labels["balance"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mod.rs index 4fce68600..d81042764 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mod.rs @@ -30,6 +30,7 @@ use std::{ops::Range, str::FromStr}; use anyhow::Result; use ethereum_types::U256; +use mpt_trie::partial_trie::HashedPartialTrie; use plonky2::hash::hash_types::RichField; use super::{ @@ -323,3 +324,36 @@ impl Interpreter { self.generation_state.registers.context = context; } } + +#[cfg(feature = "eth_mainnet")] +use std::collections::BTreeMap; + +#[cfg(feature = "eth_mainnet")] +use keccak_hash::H256; + +#[cfg(feature = "eth_mainnet")] +use crate::world::{ + tries::StateMpt, + world::{StateWorld, Type1World}, +}; + +#[cfg(feature = "eth_mainnet")] +fn get_state_world_from_trie_and_storage( + state_trie: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + use either::Either; + + use crate::world::tries::StorageTrie; + + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs index 72edba94f..57ba15b88 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs @@ -10,8 +10,10 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; -use crate::cpu::kernel::tests::mpt::{nibbles_64, test_account_1_rlp, test_account_2}; -use crate::generation::mpt::AccountRlp; +use crate::cpu::kernel::tests::mpt::{ + get_state_world_no_storage, nibbles_64, test_account_1_rlp, test_account_2, +}; +use crate::generation::mpt::MptAccountRlp; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -19,7 +21,8 @@ use crate::Node; #[test] fn mpt_delete_empty() -> Result<()> { - test_state_trie(Default::default(), nibbles_64(0xABC), test_account_2()) + let test_account = test_account_2(); + test_state_trie(Default::default(), nibbles_64(0xABC), test_account) } #[test] @@ -85,18 +88,19 @@ fn test_after_mpt_delete_extension_branch() -> Result<()> { fn test_state_trie( state_trie: HashedPartialTrie, k: Nibbles, - mut account: AccountRlp, + mut account: MptAccountRlp, ) -> Result<()> { assert_eq!(k.count, 64); // Ignore any storage_root; see documentation note. account.storage_root = HashedPartialTrie::from(Node::Empty).hash(); + let state_world = get_state_world_no_storage(state_trie.clone()); let trie_inputs = TrieInputs { - state_trie: state_trie.clone(), + state_trie: state_world, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let mpt_delete = KERNEL.global_labels["mpt_delete"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs index 202add7e9..884375d77 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs @@ -1,14 +1,15 @@ use anyhow::Result; use ethereum_types::{BigEndianHash, H256}; -use mpt_trie::partial_trie::PartialTrie; use plonky2::field::goldilocks_field::GoldilocksField as F; +use super::get_state_world_no_storage; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1_rlp, test_account_2_rlp}; use crate::generation::TrieInputs; +use crate::world::world::World; use crate::Node; // TODO: Test with short leaf. Might need to be a storage trie. @@ -28,11 +29,13 @@ fn mpt_hash_empty() -> Result<()> { #[test] fn mpt_hash_empty_branch() -> Result<()> { let children = core::array::from_fn(|_| Node::Empty.into()); - let state_trie = Node::Branch { - children, - value: vec![], - } - .into(); + let state_trie = get_state_world_no_storage( + Node::Branch { + children, + value: vec![], + } + .into(), + ); let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), @@ -45,11 +48,13 @@ fn mpt_hash_empty_branch() -> Result<()> { #[test] fn mpt_hash_hash() -> Result<()> { let hash = H256::random(); + + let state_trie = get_state_world_no_storage(Node::Hash(hash).into()); let trie_inputs = TrieInputs { - state_trie: Node::Hash(hash).into(), + state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; test_state_trie(trie_inputs) @@ -57,28 +62,30 @@ fn mpt_hash_hash() -> Result<()> { #[test] fn mpt_hash_leaf() -> Result<()> { - let state_trie = Node::Leaf { - nibbles: 0xABC_u64.into(), - value: test_account_1_rlp(), - } - .into(); + let state_trie = get_state_world_no_storage( + Node::Leaf { + nibbles: 0xABC_u64.into(), + value: test_account_1_rlp(), + } + .into(), + ); let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; test_state_trie(trie_inputs) } #[test] fn mpt_hash_extension_to_leaf() -> Result<()> { - let state_trie = extension_to_leaf(test_account_1_rlp()); + let state_trie = get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())); let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; test_state_trie(trie_inputs) } @@ -93,17 +100,19 @@ fn mpt_hash_branch_to_leaf() -> Result<()> { let mut children = core::array::from_fn(|_| Node::Empty.into()); children[3] = leaf; - let state_trie = Node::Branch { - children, - value: vec![], - } - .into(); + let state_trie = get_state_world_no_storage( + Node::Branch { + children, + value: vec![], + } + .into(), + ); let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; test_state_trie(trie_inputs) @@ -138,7 +147,7 @@ fn test_state_trie(trie_inputs: TrieInputs) -> Result<()> { interpreter.stack() ); let hash = H256::from_uint(&interpreter.stack()[1]); - let expected_state_trie_hash = trie_inputs.state_trie.hash(); + let expected_state_trie_hash = trie_inputs.state_trie.state.unwrap_left().root(); assert_eq!(hash, expected_state_trie_hash); Ok(()) diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs index 7428044d1..b72967520 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs @@ -1,4 +1,7 @@ +use std::collections::BTreeMap; + use anyhow::Result; +use either::Either; use ethereum_types::{BigEndianHash, H256}; use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; @@ -12,10 +15,12 @@ use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{ nibbles_64, nibbles_count, test_account_1_rlp, test_account_2, }; -use crate::generation::mpt::AccountRlp; +use crate::generation::mpt::MptAccountRlp; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; +use crate::world::tries::StateMpt; +use crate::world::world::{StateWorld, Type1World}; use crate::Node; #[test] @@ -161,18 +166,28 @@ fn mpt_insert_branch_to_leaf_same_key() -> Result<()> { fn test_state_trie( mut state_trie: HashedPartialTrie, k: Nibbles, - mut account: AccountRlp, + mut account: MptAccountRlp, ) -> Result<()> { assert_eq!(k.count, 64); + let state_trie_inputs = StateWorld { + state: Either::Left( + Type1World::new( + StateMpt::new_with_inner(state_trie.clone()), + BTreeMap::default(), + ) + .unwrap(), + ), + }; + // Ignore any storage_root; see documentation note. account.storage_root = HashedPartialTrie::from(Node::Empty).hash(); let trie_inputs = TrieInputs { - state_trie: state_trie.clone(), + state_trie: state_trie_inputs, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs index 9d04700bf..5f8eeb973 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs @@ -1,6 +1,8 @@ +use std::collections::BTreeMap; use std::str::FromStr; use anyhow::Result; +use either::Either; use ethereum_types::{BigEndianHash, H256, U256}; use hex_literal::hex; use mpt_trie::nibbles::Nibbles; @@ -11,8 +13,12 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::trie_type::PartialTrieType; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; -use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1, test_account_1_rlp}; +use crate::cpu::kernel::tests::mpt::{ + extension_to_leaf, get_state_world_no_storage, test_account_1, test_account_1_rlp, +}; use crate::generation::TrieInputs; +use crate::world::tries::StateMpt; +use crate::world::world::{StateWorld, Type1World}; use crate::Node; #[test] @@ -21,7 +27,7 @@ fn load_all_mpts_empty() -> Result<()> { state_trie: Default::default(), transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let initial_stack = vec![]; @@ -50,15 +56,18 @@ fn load_all_mpts_empty() -> Result<()> { #[test] fn load_all_mpts_leaf() -> Result<()> { - let trie_inputs = TrieInputs { - state_trie: Node::Leaf { + let state_trie = get_state_world_no_storage( + Node::Leaf { nibbles: 0xABC_u64.into(), value: test_account_1_rlp(), } .into(), + ); + let trie_inputs = TrieInputs { + state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let initial_stack = vec![]; @@ -106,11 +115,22 @@ fn load_all_mpts_leaf() -> Result<()> { #[test] fn load_all_mpts_hash() -> Result<()> { let hash = H256::random(); + + let state_trie = StateWorld { + state: Either::Left( + Type1World::new( + StateMpt::new_with_inner(Node::Hash(hash).into()), + BTreeMap::default(), + ) + .unwrap(), + ), + }; + let trie_inputs = TrieInputs { - state_trie: Node::Hash(hash).into(), + state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let initial_stack = vec![]; @@ -139,16 +159,26 @@ fn load_all_mpts_hash() -> Result<()> { #[test] fn load_all_mpts_empty_branch() -> Result<()> { let children = core::array::from_fn(|_| Node::Empty.into()); - let state_trie = Node::Branch { - children, - value: vec![], - } - .into(); + let state_trie = StateWorld { + state: Either::Left( + Type1World::new( + StateMpt::new_with_inner( + Node::Branch { + children, + value: vec![], + } + .into(), + ), + BTreeMap::default(), + ) + .unwrap(), + ), + }; let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let initial_stack = vec![]; @@ -197,10 +227,10 @@ fn load_all_mpts_empty_branch() -> Result<()> { #[test] fn load_all_mpts_ext_to_leaf() -> Result<()> { let trie_inputs = TrieInputs { - state_trie: extension_to_leaf(test_account_1_rlp()), + state_trie: get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())), transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let initial_stack = vec![]; @@ -252,7 +282,7 @@ fn load_mpt_txn_trie() -> Result<()> { value: txn.clone(), }), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let initial_stack = vec![]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 76e83f362..7a9ceedc0 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeMap; + use either::Either; use ethereum_types::{BigEndianHash, H256, U256}; use mpt_trie::nibbles::Nibbles; @@ -7,6 +9,9 @@ use mpt_trie::partial_trie::PartialTrie; use crate::generation::mpt::EitherRlp; use crate::generation::mpt::MptAccountRlp; use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; +use crate::world::tries::StateMpt; +use crate::world::world::StateWorld; +use crate::world::world::Type1World; use crate::Node; #[cfg(feature = "eth_mainnet")] @@ -61,27 +66,26 @@ pub(crate) fn test_account_1_empty_storage() -> EitherRlp { } } -// #[cfg(feature = "eth_mainnet")] -pub(crate) fn test_account_1() -> EitherRlp { - if cfg!(feature = "cdk_erigon") { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - code_hash: U256::from(4444), - code_length: 0.into(), - }), - } - } else { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - storage_root: H256::from_uint(&U256::from(3333)), - code_hash: H256::from_uint(&U256::from(4444)), - }), - } +#[cfg(feature = "eth_mainnet")] +pub(crate) fn test_account_1() -> MptAccountRlp { + // if cfg!(feature = "cdk_erigon") { + // EitherRlp { + // account_rlp: Either::Right(SmtAccountRlp { + // nonce: U256::from(1111), + // balance: U256::from(2222), + // code_hash: U256::from(4444), + // code_length: 0.into(), + // }), + // } + // } else { + MptAccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: H256::from_uint(&U256::from(3333)), + code_hash: H256::from_uint(&U256::from(4444)), } + + // } } // #[cfg(feature = "cdk_erigon")] // pub(crate) fn test_account_1() -> Box { @@ -111,28 +115,26 @@ pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { test_account_1_empty_storage().rlp_encode().to_vec() } -// #[cfg(feature = "eth_mainnet")] -pub(crate) fn test_account_2() -> EitherRlp { - if cfg!(feature = "cdk_erigon") { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: U256::from(5555), - balance: U256::from(6666), - code_hash: U256::from(8888), - code_length: 0.into(), - }), - } - } else { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: U256::from(5555), - balance: U256::from(6666), - storage_root: H256::from_uint(&U256::from(7777)), - code_hash: H256::from_uint(&U256::from(8888)), - }), - } +#[cfg(feature = "eth_mainnet")] +pub(crate) fn test_account_2() -> MptAccountRlp { + // if cfg!(feature = "cdk_erigon") { + // EitherRlp { + // account_rlp: Either::Right(SmtAccountRlp { + // nonce: U256::from(5555), + // balance: U256::from(6666), + // code_hash: U256::from(8888), + // code_length: 0.into(), + // }), + // } + // } else { + MptAccountRlp { + nonce: U256::from(5555), + balance: U256::from(6666), + storage_root: H256::from_uint(&U256::from(7777)), + code_hash: H256::from_uint(&U256::from(8888)), } } +// } // #[cfg(feature = "cdk_erigon")] // pub(crate) fn test_account_2() -> Box { @@ -166,3 +168,12 @@ pub(crate) fn extension_to_leaf(value: Vec) -> HashedPartialTrie { } .into() } + +#[cfg(feature = "eth_mainnet")] +pub(crate) fn get_state_world_no_storage(state_trie: HashedPartialTrie) -> StateWorld { + StateWorld { + state: Either::Left( + Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(), + ), + } +} diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs index 8390c6a59..fe3ff467b 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs @@ -6,16 +6,18 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; -use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1, test_account_1_rlp}; +use crate::cpu::kernel::tests::mpt::{ + extension_to_leaf, get_state_world_no_storage, test_account_1, test_account_1_rlp, +}; use crate::generation::TrieInputs; #[test] fn mpt_read() -> Result<()> { let trie_inputs = TrieInputs { - state_trie: extension_to_leaf(test_account_1_rlp()), + state_trie: get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())), transactions_trie: Default::default(), receipts_trie: Default::default(), - storage_tries: vec![], + // storage_tries: vec![], }; let mpt_read = KERNEL.global_labels["mpt_read"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs b/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs index b80a3772a..aa69dc3a9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use either::Either; use ethereum_types::{Address, U256}; use hex_literal::hex; use keccak_hash::H256; @@ -10,17 +11,19 @@ use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::prepare_interpreter; use crate::cpu::kernel::tests::transaction_parsing::prepare_interpreter_for_txn_parsing; -use crate::generation::mpt::AccountRlp; +use crate::generation::mpt::{EitherRlp, MptAccountRlp}; use crate::testing_utils::EMPTY_NODE_HASH; #[test] fn process_type_3_txn() -> Result<()> { let sender_address = Address::from_slice(&hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")); - let sender_account = AccountRlp { - nonce: 1.into(), - balance: 0x1000000.into(), - storage_root: EMPTY_NODE_HASH, - code_hash: H256::default(), + let sender_account = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + balance: 0x1000000.into(), + storage_root: EMPTY_NODE_HASH, + code_hash: H256::default(), + }), }; let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); @@ -107,11 +110,13 @@ fn process_type_3_txn() -> Result<()> { #[test] fn process_type_3_txn_invalid_sig() -> Result<()> { let sender_address = Address::from_slice(&hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")); - let sender_account = AccountRlp { - nonce: 1.into(), - balance: 0x1000000.into(), - storage_root: EMPTY_NODE_HASH, - code_hash: H256::default(), + let sender_account = EitherRlp { + account_rlp: Either::Left(MptAccountRlp { + nonce: 1.into(), + balance: 0x1000000.into(), + storage_root: EMPTY_NODE_HASH, + code_hash: H256::default(), + }), }; let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index b3beb5e9f..2fe63834e 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -39,7 +39,7 @@ use crate::proof::{ use crate::util::{h2u, u256_to_usize}; use crate::witness::memory::{MemoryAddress, MemoryChannel, MemoryState}; use crate::witness::state::RegistersState; -use crate::world::world::{StateWorld, Type1World, Type2World}; +use crate::world::world::StateWorld; pub(crate) mod linked_list; pub mod mpt; @@ -199,7 +199,6 @@ pub struct TrimmedGenerationInputs { #[cfg(feature = "cdk_erigon")] type SmtTrie = smt_trie::smt::Smt; -trait StateTrie {} #[derive(Clone, Debug, Deserialize, Serialize, Default)] pub struct TrieInputs { /// A partial version of the state trie prior to these transactions. It diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 46247112a..179ebeff7 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -53,9 +53,9 @@ pub struct MptAccountRlp { } impl AccountRlp for MptAccountRlp { - fn as_any(&self) -> &dyn Any { - self - } + // fn as_any(&self) -> &dyn Any { + // self + // } fn get_nonce(&self) -> U256 { self.nonce } @@ -88,9 +88,9 @@ pub struct SmtAccountRlp { } impl AccountRlp for SmtAccountRlp { - fn as_any(&self) -> &dyn Any { - self - } + // fn as_any(&self) -> &dyn Any { + // self + // } fn get_nonce(&self) -> U256 { self.nonce } @@ -122,7 +122,7 @@ pub trait AccountRlp: Any { fn get_code_hash(&self) -> CodeHashType; fn get_code_hash_u256(&self) -> U256; fn rlp_encode(&self) -> BytesMut; - fn as_any(&self) -> &dyn Any; + // fn as_any(&self) -> &dyn Any; } pub struct EitherRlp { @@ -130,6 +130,7 @@ pub struct EitherRlp { } impl EitherRlp { + #[cfg(test)] pub(crate) fn rlp_encode(&self) -> BytesMut { match &self.account_rlp { Either::Left(mpt_acct) => mpt_acct.rlp_encode(), @@ -152,6 +153,51 @@ impl EitherRlp { } } +impl AccountRlp for EitherRlp { + fn get_nonce(&self) -> U256 { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.get_nonce(), + Either::Right(smt_rlp) => smt_rlp.get_nonce(), + } + } + fn get_balance(&self) -> U256 { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.get_balance(), + Either::Right(smt_rlp) => smt_rlp.get_balance(), + } + } + fn get_storage_root(&self) -> H256 { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.get_storage_root(), + Either::Right(smt_rlp) => smt_rlp.get_storage_root(), + } + } + fn get_code_length(&self) -> U256 { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.get_code_length(), + Either::Right(smt_rlp) => smt_rlp.get_code_length(), + } + } + fn get_code_hash(&self) -> CodeHashType { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.get_code_hash(), + Either::Right(smt_rlp) => smt_rlp.get_code_hash(), + } + } + fn get_code_hash_u256(&self) -> U256 { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.get_code_hash_u256(), + Either::Right(smt_rlp) => smt_rlp.get_code_hash_u256(), + } + } + fn rlp_encode(&self) -> BytesMut { + match self.account_rlp { + Either::Left(mpt_rlp) => mpt_rlp.rlp_encode(), + Either::Right(smt_rlp) => smt_rlp.rlp_encode(), + } + } +} + impl Default for EitherRlp { fn default() -> Self { EitherRlp { diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 306069586..a866f7bf3 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -101,9 +101,9 @@ impl GenerationState { .map_or_else( || { let mut new_content = self.memory.get_preinit_memory(Segment::TrieData); - let mut n = Err(ProgramError::ProverInputError( - ProverInputError::InvalidInput, - )); + // let mut n = Err(ProgramError::ProverInputError( + // ProverInputError::InvalidInput, + // )); // #[cfg(feature = "eth_mainnet")] // { // n = load_state_mpt(&self.inputs.trimmed_tries, &mut new_content); @@ -117,7 +117,7 @@ impl GenerationState { // } // #[cfg(feature = "cdk_erigon")] // { - n = if cfg!(feature = "cdk_erigon") { + let n = if cfg!(feature = "cdk_erigon") { Ok(new_content.len()) } else { load_state_mpt(&self.inputs.trimmed_tries, &mut new_content) diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index e9245aeda..8425386c7 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -18,9 +18,9 @@ use crate::byte_packing::byte_packing_stark::BytePackingOp; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::stack::MAX_USER_STACK_SIZE; -use crate::generation::linked_list::{ - empty_list_mem, AccessLinkedListsPtrs, StateLinkedListsPtrs, STATE_LINKED_LIST_NODE_SIZE, -}; +#[cfg(feature = "cdk_erigon")] +use crate::generation::linked_list::{empty_list_mem, STATE_LINKED_LIST_NODE_SIZE}; +use crate::generation::linked_list::{AccessLinkedListsPtrs, StateLinkedListsPtrs}; #[cfg(feature = "eth_mainnet")] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; use crate::generation::mpt::{load_receipts_mpt, load_transactions_mpt}; diff --git a/evm_arithmetization/src/generation/trie_extractor.rs b/evm_arithmetization/src/generation/trie_extractor.rs index eda8dafff..c13d56625 100644 --- a/evm_arithmetization/src/generation/trie_extractor.rs +++ b/evm_arithmetization/src/generation/trie_extractor.rs @@ -5,7 +5,7 @@ use ethereum_types::{BigEndianHash, H256, U256}; use mpt_trie::nibbles::{Nibbles, NibblesIntern}; use mpt_trie::partial_trie::{HashedPartialTrie, Node, PartialTrie, WrappedNode}; -use super::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp}; +use super::mpt::{LegacyReceiptRlp, LogRlp}; use crate::cpu::kernel::constants::trie_type::PartialTrieType; use crate::memory::segments::Segment; use crate::util::{u256_to_bool, u256_to_h160, u256_to_u8, u256_to_usize}; diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index 44a3641ee..664cf2de2 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -7,7 +7,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::generation::mpt::{ - AccountRlp, EitherRlp, LegacyReceiptRlp, MptAccountRlp, SmtAccountRlp, + AccountRlp, EitherRlp, LegacyReceiptRlp, MptAccountRlp, }; use evm_arithmetization::generation::TrieInputs; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index 3d95965a9..8bac6c2ae 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -6,7 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index ecf931680..546c6360c 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -6,7 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 0efe66f0e..47a50315d 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -10,7 +10,7 @@ use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::generation::mpt::transaction_testing::{ AddressOption, LegacyTransactionRlp, }; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index ea5668079..2824be6c3 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -6,7 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index fc2d483e2..506edd073 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -6,7 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index 58a4e1d72..5004d3e0b 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -5,7 +5,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::MptAccountRlp; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; From f3fbbe9b18ea0cace016ebcba1d41160284c4cbb Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 4 Nov 2024 16:53:43 +0100 Subject: [PATCH 42/60] Fix all compilation errors --- .../benches/fibonacci_25m_gas.rs | 21 +++++++++---------- .../src/cpu/kernel/asm/core/process_txn.asm | 9 +++++++- .../src/cpu/kernel/interpreter.rs | 14 +++++++++---- .../src/cpu/kernel/tests/account_code.rs | 6 ++++++ .../src/cpu/kernel/tests/mpt/mod.rs | 2 ++ evm_arithmetization/src/generation/mod.rs | 2 -- 6 files changed, 36 insertions(+), 18 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index a68713bcb..339cfc4bc 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -10,6 +10,8 @@ use std::str::FromStr; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use either::Either; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; +#[cfg(feature = "cdk_erigon")] +use ethereum_types::H160; use ethereum_types::{Address, BigEndianHash, H256, U256}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; @@ -38,12 +40,9 @@ use plonky2::field::types::Field; #[cfg(feature = "cdk_erigon")] use plonky2::field::types::PrimeField64; use smt_trie::code::hash_bytecode_u256; -use smt_trie::utils::hashout2u; #[cfg(feature = "cdk_erigon")] -use smt_trie::{ - keys::{key_balance, key_code_length}, - utils::hashout2u, -}; +use smt_trie::keys::{key_balance, key_code_length}; +use smt_trie::utils::hashout2u; type F = GoldilocksField; @@ -214,7 +213,7 @@ fn prepare_setup() -> anyhow::Result> { { let sender_account_before_smt = sender_account_before.expect_right("The sender account is an SMT."); - let to_account_before_smt = to_account_before.expect_right("The sender account is an SMT."); + let to_account_before_smt = to_account_before.as_smt_account_rlp(); set_account( &mut state_trie_before, H160(sender), @@ -339,9 +338,8 @@ fn prepare_setup() -> anyhow::Result> { #[cfg(feature = "cdk_erigon")] { - let sender_account_after_smt = - sender_account_after.expect_right("cdk_erigon expects an SMT."); - let to_account_after_smt = to_account_after.expect_right("cdk_erigon expects an SMT."); + let sender_account_after_smt = sender_account_after.as_smt_account_rlp(); + let to_account_after_smt = to_account_after.as_smt_account_rlp(); set_account( &mut expected_state_trie_after, H160(sender), @@ -458,10 +456,11 @@ fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, c // smt.set(key_storage(addr, k), v); // } } +#[cfg(feature = "eth_mainnet")] use std::collections::BTreeMap; -use evm_arithmetization::world::tries::StateMpt; -use evm_arithmetization::world::world::Type1World; +#[cfg(feature = "eth_mainnet")] +use evm_arithmetization::world::{tries::StateMpt, world::Type1World}; #[cfg(feature = "eth_mainnet")] fn get_state_world_from_trie_and_storage( state_trie: HashedPartialTrie, diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 987bfceab..46e5aa33a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -218,7 +218,14 @@ process_contract_creation_txn_after_ef_check: GET_CONTEXT %build_address_no_offset // stack: addr, len, leftover_gas, new_ctx, address, retdest, success - %poseidon_hash_code_unpadded + #[cfg(feature = cdk_erigon)] + { + %poseidon_hash_code_unpadded + } + #[cfg(feature = eth_mainnet)] + { + KECCAK_GENERAL + } // stack: codehash, leftover_gas, new_ctx, address, retdest, success %observe_new_contract DUP4 diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 1ea6dcbc6..51232b533 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -309,7 +309,15 @@ impl Interpreter { .state_trie() .hash()), #[cfg(feature = "cdk_erigon")] - hash_serialize_u256(&smt.as_smt().to_vec()), + hash_serialize_u256( + &tries + .state_trie + .state + .clone() + .expect_right("cdk_erigon expects SMTs.") + .as_smt() + .to_vec(), + ), /* match &tries.state_trie.state { * Either::Left(mpt) => * h2u(mpt.state_trie().hash()), @@ -415,9 +423,7 @@ impl Interpreter { self.generation_state.memory.set(address, value); } } - MemoryOpKind::Write => { - self.generation_state.memory.set(address, value) - } + MemoryOpKind::Write => self.generation_state.memory.set(address, value), } } diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 667d10d72..f433e51f9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use either::Either; +use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; use ethereum_types::{Address, BigEndianHash, H256, U256}; use hex_literal::hex; use keccak_hash::keccak; @@ -552,6 +553,7 @@ fn prepare_interpreter_all_accounts( #[test] #[cfg(feature = "eth_mainnet")] fn sstore() -> Result<()> { + init_logger(); // We take the same `to` account as in add11_yml. let addr = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); @@ -779,3 +781,7 @@ pub(crate) fn get_state_world_no_storage(state_trie: HashedPartialTrie) -> State ), } } + +fn init_logger() { + let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); +} diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 7a9ceedc0..637aea902 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -107,6 +107,7 @@ pub(crate) fn test_account_1() -> MptAccountRlp { // }) // } +#[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_1_rlp() -> Vec { test_account_1().rlp_encode().to_vec() } @@ -148,6 +149,7 @@ pub(crate) fn test_account_2() -> MptAccountRlp { // }) // } +#[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_2_rlp() -> Vec { test_account_2().rlp_encode().to_vec() } diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 2fe63834e..ddcc191ad 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -15,8 +15,6 @@ use plonky2::util::timing::TimingTree; use segments::GenerationSegmentData; use serde::{Deserialize, Serialize}; use smt_trie::smt::hash_serialize_u256; -#[cfg(feature = "cdk_erigon")] -use smt_trie::smt::hash_serialize_u256; use starky::config::StarkConfig; use GlobalMetadata::{ ReceiptTrieRootDigestAfter, ReceiptTrieRootDigestBefore, StateTrieRootDigestAfter, From 00c62925627d013803e9c1a8559e69b4bb73d6e0 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 4 Nov 2024 19:31:14 +0100 Subject: [PATCH 43/60] Some cleanup --- evm_arithmetization/Cargo.toml | 2 +- .../benches/fibonacci_25m_gas.rs | 82 ------------------- .../src/cpu/kernel/asm/account_code.asm | 3 - .../src/cpu/kernel/asm/cdk_pre_execution.asm | 6 -- .../src/cpu/kernel/asm/core/call.asm | 1 - .../src/cpu/kernel/asm/core/call_gas.asm | 1 - .../src/cpu/kernel/asm/core/create.asm | 11 --- .../core/create_type2_contract_account.asm | 4 +- .../src/cpu/kernel/asm/core/process_txn.asm | 11 --- .../cpu/kernel/asm/core/selfdestruct_list.asm | 1 - .../cpu/kernel/asm/core/touched_addresses.asm | 4 - .../asm/linked_list/type2/final_tries.asm | 2 - .../asm/linked_list/type2/initial_tries.asm | 4 - .../linked_list/type2/state_linked_list.asm | 7 -- .../src/cpu/kernel/asm/main.asm | 6 -- .../src/cpu/kernel/asm/memory/syscalls.asm | 7 -- .../asm/mpt/hash/hash_trie_specific.asm | 1 - .../src/cpu/kernel/asm/smt/read.asm | 11 --- .../asm/transactions/common_decoding.asm | 2 - .../cpu/kernel/asm/transactions/type_0.asm | 1 - .../src/cpu/kernel/constants/mod.rs | 2 - .../src/cpu/kernel/interpreter.rs | 7 -- .../src/cpu/kernel/tests/account_code.rs | 51 ------------ .../src/cpu/kernel/tests/balance.rs | 14 ---- .../src/cpu/kernel/tests/init_exc_stop.rs | 13 +-- .../src/cpu/kernel/tests/mpt/delete.rs | 1 - .../src/cpu/kernel/tests/mpt/hash.rs | 6 -- .../src/cpu/kernel/tests/mpt/insert.rs | 1 - .../src/cpu/kernel/tests/mpt/load.rs | 6 -- .../src/cpu/kernel/tests/mpt/mod.rs | 55 ------------- .../src/cpu/kernel/tests/mpt/read.rs | 1 - evm_arithmetization/src/generation/mod.rs | 45 ++-------- evm_arithmetization/src/generation/mpt.rs | 9 -- .../src/generation/prover_input.rs | 79 ++++-------------- evm_arithmetization/src/generation/state.rs | 38 --------- evm_arithmetization/src/prover.rs | 1 - evm_arithmetization/src/testing_utils.rs | 12 +-- evm_arithmetization/src/witness/operation.rs | 2 - evm_arithmetization/src/witness/transition.rs | 31 ------- evm_arithmetization/src/world/world.rs | 4 - evm_arithmetization/tests/erc20_type2.rs | 29 ------- smt_trie/src/code.rs | 4 - 42 files changed, 25 insertions(+), 553 deletions(-) diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index e73306979..201edab51 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -52,7 +52,7 @@ serde = { workspace = true, features = ["derive"] } serde-big-array.workspace = true serde_json.workspace = true sha2.workspace = true -smt_trie = { workspace = true } +smt_trie.workspace = true starky = { workspace = true, features = ["parallel"] } static_assertions.workspace = true stackstack = "0.3.0" diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 339cfc4bc..32eefdffe 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -27,8 +27,6 @@ use evm_arithmetization::testing_utils::{ beacon_roots_account_nibbles, beacon_roots_contract_from_storage, preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; -// #[cfg(feature = "cdk_erigon")] -// use evm_arithmetization::util::h2u; use evm_arithmetization::world::world::StateWorld; use evm_arithmetization::{Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; @@ -93,27 +91,9 @@ fn prepare_setup() -> anyhow::Result> { } else { CodeHashType::Hash(keccak(code)) }; - // let code_hash = keccak(code); - // #[cfg(feature = "cdk_erigon")] - // let code_hash = CodeHashType::Uint(hash_bytecode_u256(code.to_vec())); let empty_trie_root = HashedPartialTrie::from(Node::Empty).hash(); - // #[cfg(feature = "eth_mainnet")] - // let sender_account_before = Box::new(MptAccountRlp { - // nonce: 169.into(), - // balance: U256::from_dec_str("999999999998417410153631615")?, - // storage_root: empty_trie_root, - // code_hash: keccak(vec![]), - // }); - // #[cfg(feature = "eth_mainnet")] - // let to_account_before = Box::new(MptAccountRlp { - // nonce: 1.into(), - // balance: 0.into(), - // storage_root: empty_trie_root, - // code_hash, - // }); - let sender_account_before = if cfg!(feature = "cdk_erigon") { Either::Right(SmtAccountRlp { nonce: 169.into(), @@ -152,41 +132,6 @@ fn prepare_setup() -> anyhow::Result> { } }; - // #[cfg(feature = "cdk_erigon")] - // let sender_account_before: Box = if cfg!(feature = - // "cdk_erigon") { Box::new(SmtAccountRlp { - // nonce: 169.into(), - // balance: U256::from_dec_str("999999999998417410153631615")?, - // code_hash: hash_bytecode_u256(vec![]), - // code_length: 0.into(), - // }) - // } else { - // Box::new(MptAccountRlp { - // nonce: 169.into(), - // balance: U256::from_dec_str("999999999998417410153631615")?, - // storage_root: empty_trie_root, - // code_hash: keccak(vec![]), - // }) - // }; - // #[cfg(feature = "cdk_erigon")] - // let to_account_before: Box = if cfg!(feature = "cdk_erigon") - // { Box::new(SmtAccountRlp { - // nonce: 1.into(), - // balance: 0.into(), - // code_hash: get_u256_from_code_hash(code_hash.clone()) - // .expect("In cdk_erigon, the code_hash is a U256"), - // code_length: code.len().into(), - // }) - // } else { - // Box::new(MptAccountRlp { - // nonce: 1.into(), - // balance: 0.into(), - // storage_root: empty_trie_root, - // code_hash: get_h256_from_code_hash(code_hash.clone()) - // .expect("In eth_mainnet, the code_hash is a H256"), - // }) - // }; - let mut state_trie_before = StateWorld::default(); #[cfg(feature = "eth_mainnet")] let (mut state_trie_before_hashed, mut storage_tries) = @@ -229,14 +174,9 @@ fn prepare_setup() -> anyhow::Result> { } let tries_before = TrieInputs { - // #[cfg(feature = "eth_mainnet")] - // state_trie: state_trie_before, - // #[cfg(feature = "cdk_erigon")] state_trie: state_trie_before, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - // #[cfg(feature = "eth_mainnet")] - // storage_tries, }; let gas_used = U256::from(0x17d7840_u32); @@ -270,19 +210,6 @@ fn prepare_setup() -> anyhow::Result> { contract_code.insert(empty_code_hash, vec![]); contract_code.insert(code_hash, code.to_vec()); } - // #[cfg(feature = "eth_mainnet")] - // { - // contract_code.insert(keccak(vec![]), vec![]); - // contract_code.insert(code_hash, code.to_vec()); - // } - // #[cfg(feature = "cdk_erigon")] - // { - // contract_code.insert(hash_bytecode_u256(vec![]), vec![]); - // contract_code.insert( - // get_u256_from_code_hash(code_hash).expect("In cdk_erigon, the - // code_hash is a U256"), code.to_vec(), - // ); - // } let sender_account_after = if cfg!(feature = "cdk_erigon") { let sender_account_before_smt = @@ -387,10 +314,6 @@ fn prepare_setup() -> anyhow::Result> { )) }; let trie_roots_after = TrieRoots { - // #[cfg(feature = "eth_mainnet")] - // state_root: expected_state_trie_after.hash(), - // #[cfg(feature = "cdk_erigon")] - // state_root: H256::from_uint(&hashout2u(expected_smt_after.root)), state_root, transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), @@ -450,11 +373,6 @@ fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, c U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) ); } - - // smt.set(key_code_length(addr), account.code_length); - // for (&k, &v) in storage { - // smt.set(key_storage(addr, k), v); - // } } #[cfg(feature = "eth_mainnet")] use std::collections::BTreeMap; diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 7601dde6b..550b85ae6 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -120,7 +120,6 @@ load_code_ctd: // stack: codehash, ctx, retdest DUP1 ISZERO %jumpi(load_code_non_existent_account) // Load the code non-deterministically in memory and return the length. -global debug_account_code: PROVER_INPUT(account_code) #[cfg(feature = eth_mainnet)] { @@ -220,8 +219,6 @@ load_code_padded_ctd: DUP1 %jumpi(non_zero_padding) %jump(padd) non_zero_padding: -global debug_len_mod_56: - // curr_len mod 56, padding_addr, addr, len, retdest PUSH 56 SUB padd: diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index a1ce0544c..42867abec 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -15,21 +15,17 @@ global pre_block_execution: global update_scalable_block_number: // stack: retdest %blocknumber -global debug_blocknumber: PUSH @LAST_BLOCK_STORAGE_POS // stack: last_block_slot, block_number, retdest %write_scalable_storage // stack: retdest -global debug_wtf_is_happening_with_retdest: // Check timestamp PUSH @TIMESTAMP_STORAGE_POS PUSH @ADDRESS_SCALABLE_L2 %read_slot_from_addr_key // stack: old_timestamp, retdest %timestamp -global debug_el_timestamp: GT -global debug_before_jumpi: %jumpi(update_scalable_timestamp) global update_scalable_prev_block_root_hash: @@ -91,7 +87,6 @@ skip_and_exit: global update_scalable_timestamp: // stack: retdest %timestamp -global debug_le_timestamp: PUSH @TIMESTAMP_STORAGE_POS // stack: timestamp_slot, timestamp, retdest %write_scalable_storage @@ -107,7 +102,6 @@ global create_scalable_l2_account: // stack: retdest PUSH @EMPTY_STRING_POSEIDON_HASH PUSH @ADDRESS_SCALABLE_L2 -global debug_setting_scalable_code: %set_code // code hash // stack: retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/call.asm b/evm_arithmetization/src/cpu/kernel/asm/core/call.asm index 05d2f1944..786a13f0c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/call.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/call.asm @@ -25,7 +25,6 @@ global sys_call: DUP1 %insert_accessed_addresses %call_charge_gas(1, 1) -global debug_after_charge_gas: %check_depth %checkpoint // Checkpoint diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm b/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm index 9a2262fc9..c70de697b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/call_gas.asm @@ -53,7 +53,6 @@ after_new_cost: %charge_gas // Compute C_callgas -global debug_por_aca: %stack (kexit_info, Cgascap, address, gas, value) -> (Cgascap, address, gas, kexit_info, value) DUP5 ISZERO %not_bit diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index 5f4d1fd68..502f51d55 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -92,7 +92,6 @@ global create_common: %create_context // stack: new_ctx, address, value, code_offset, code_len, kexit_info -global debug_new_ctx: GET_CONTEXT // stack: src_ctx, new_ctx, address, value, code_offset, code_len, kexit_info @@ -114,16 +113,13 @@ global debug_new_ctx: run_constructor: // stack: new_ctx, value, address, kexit_info -global debug_run_constructor: SWAP1 %set_new_ctx_value -global debug_1: // stack: new_ctx, address, kexit_info // Each line in the block below does not change the stack. DUP2 %set_new_ctx_addr %address %set_new_ctx_caller %set_new_ctx_parent_pc(after_constructor) -global debug_2: // stack: new_ctx, address, kexit_info // All but 1/64 of the sender's remaining gas goes to the constructor. @@ -136,9 +132,7 @@ global debug_2: // Create the new contract account in the state trie. DUP2 -global debug_before_create_contract_account: %create_contract_account -global debug_after_create_contract_account: // stack: status, new_ctx, address, kexit_info %jumpi(create_collision) @@ -185,7 +179,6 @@ after_constructor: #[cfg(feature = cdk_erigon)] { %poseidon_hash_code_unpadded - global debug_poseidon_output: } // stack: codehash, leftover_gas, success, address, kexit_info %observe_new_contract @@ -284,17 +277,14 @@ global set_codehash: // stack: addr, codehash, retdest DUP1 %insert_touched_addresses DUP1 - global debug_reading_code: %read_code // stack: prev_codehash, addr, codehash, retdest DUP2 - global debug_reading_code_length: %read_code_length %stack (prev_code_length, prev_codehash, addr) -> (addr, prev_codehash, prev_code_length, prev_code_length, addr) %journal_add_code_change // Add the code change to the journal. // stack: prev_code_length, addr, codehash, retdest DUP3 DUP3 - global debug_setting_code: %set_code // stack: prev_code_length, addr, codehash, retdest %returndatasize @@ -304,7 +294,6 @@ global set_codehash: %pop3 JUMP code_length_changed: DUP2 - global debug_setting_code_lenght: %set_code_length // stack: addr, codehash, retdest %pop2 JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm index e4e244cb9..73b4b9959 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_type2_contract_account.asm @@ -44,9 +44,9 @@ // (This should be impossible with contract creation transactions or CREATE, but possible with CREATE2.) // So we return 1 to indicate an error. %%error_collision: - %stack (address) -> (1) + %stack (address) -> (1) %%end: - // stack: status + // stack: status %endmacro %macro append_created_contracts diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 46e5aa33a..4be6df775 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -16,7 +16,6 @@ global process_normalized_txn: // Assert gas_limit >= intrinsic_gas. %mload_txn_field(@TXN_FIELD_GAS_LIMIT) -global debug_invalid_txn: %assert_ge(invalid_txn) // Assert block gas limit >= txn gas limit. @@ -33,18 +32,15 @@ global debug_invalid_txn: // stack: sender_nonce, sender, retdest %mload_txn_field(@TXN_FIELD_NONCE) // stack: tx_nonce, sender_nonce, sender, retdest -global debug_eq_nonce: %assert_eq(invalid_txn_1) // stack: sender, retdest // Assert sender has no code. DUP1 %ext_code_empty -global debug_no_code: %assert_nonzero(invalid_txn_1) // stack: sender, retdest // Assert sender balance >= gas_limit * gas_price + value. -global debug_balance: %balance // stack: sender_balance, retdest %mload_txn_field(@TXN_FIELD_COMPUTED_FEE_PER_GAS) @@ -237,7 +233,6 @@ process_contract_creation_txn_after_ef_check: // stack: leftover_gas', new_ctx, address, retdest, success, leftover_gas SWAP5 POP %delete_all_touched_addresses -global debug_jump_to_delete_all_1: %delete_all_selfdestructed_addresses // stack: new_ctx, address, retdest, success, leftover_gas POP @@ -332,12 +327,10 @@ process_message_txn_after_call_contd: %pay_coinbase_and_refund_sender // stack: leftover_gas', new_ctx, retdest, success, leftover_gas SWAP4 POP -global debug_delete_all_touched: %delete_all_touched_addresses %delete_all_selfdestructed_addresses // stack: new_ctx, retdest, success, leftover_gas POP -global debug_y_salta_salta_salta: JUMP process_message_txn_fail: @@ -487,7 +480,6 @@ create_contract_account_fault: %pay_coinbase_and_refund_sender // stack: leftover_gas', retdest %delete_all_touched_addresses -global debug_jump_to_delete_all_3: %delete_all_selfdestructed_addresses // stack: leftover_gas', retdest SWAP1 PUSH 0 // success @@ -501,7 +493,6 @@ contract_creation_fault_3: %pay_coinbase_and_refund_sender // stack: leftover_gas', retdest, success %delete_all_touched_addresses -global debug_jump_to_delete_all_5: %delete_all_selfdestructed_addresses %stack (leftover_gas, retdest, success) -> (retdest, 0, leftover_gas) JUMP @@ -514,7 +505,6 @@ contract_creation_fault_3_zero_leftover: // stack: leftover_gas, retdest, success %pay_coinbase_and_refund_sender %delete_all_touched_addresses -global debug_jump_to_delete_all_6: %delete_all_selfdestructed_addresses %stack (leftover_gas, retdest, success) -> (retdest, 0, leftover_gas) JUMP @@ -527,7 +517,6 @@ contract_creation_fault_4: // stack: leftover_gas, retdest, success %pay_coinbase_and_refund_sender %delete_all_touched_addresses -global debug_jump_to_delete_all_7: %delete_all_selfdestructed_addresses %stack (leftover_gas, retdest, success) -> (retdest, 0, leftover_gas) JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm b/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm index e72263908..bf70ad447 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/selfdestruct_list.asm @@ -73,7 +73,6 @@ bingo: delete_all_selfdestructed_addresses_done: // stack: i, len, retdest %pop2 -global debug_jump_from_delete_all: JUMP %macro delete_all_selfdestructed_addresses diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm b/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm index 8d5e097db..b1e72bbec 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/touched_addresses.asm @@ -86,7 +86,6 @@ global delete_all_touched_addresses: PUSH @SEGMENT_TOUCHED_ADDRESSES ADD PUSH @SEGMENT_TOUCHED_ADDRESSES delete_all_touched_addresses_loop: -global debug_lobeando: // `i` and `len` are both scaled by SEGMENT_TOUCHED_ADDRESSES // stack: i, len, retdest DUP2 DUP2 EQ %jumpi(delete_all_touched_addresses_done) @@ -94,19 +93,16 @@ global debug_lobeando: DUP1 MLOAD_GENERAL // stack: loaded_addr, i, len, retdest DUP1 -global debug_loaded_addr: %is_empty %jumpi(bingo) // stack: loaded_addr, i, len, retdest POP %increment %jump(delete_all_touched_addresses_loop) bingo: -global debug_bingo: // stack: loaded_addr, i, len, retdest %delete_account %increment %jump(delete_all_touched_addresses_loop) delete_all_touched_addresses_done: // stack: i, len, retdest %pop2 -global debug_chaito_noma: JUMP %macro delete_all_touched_addresses diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm index 4a7951470..014b84931 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/final_tries.asm @@ -24,7 +24,6 @@ global insert_all_final_nodes: // stack: root_ptr, level, k0, k1, k2, k3, after_smt_insert, key, root_ptr, node_ptr_ptr, retdest %jump(smt_insert) after_smt_insert: -global debug_after_smt_insert: //stack: root_ptr', key, root_ptr, node_ptr_ptr, retdest %stack (new_root_ptr, key, root_ptr, next_node_ptr_ptr) -> (next_node_ptr_ptr, new_root_ptr) %next_node @@ -65,7 +64,6 @@ delete_removed_nodes_end: JUMP delete_node: -global debug_delete_node: // stack: node_ptr_ptr, root_ptr, retdest DUP1 MLOAD_GENERAL diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm index 7f3204b7c..a088fb16f 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/initial_tries.asm @@ -28,22 +28,18 @@ global insert_all_initial_nodes: // stack: key, root_ptr, node_ptr_ptr, retdest DUP3 %mload_global_metadata(@GLOBAL_METADATA_INITIAL_ACCOUNTS_LINKED_LIST_LEN) -global debug_check_no_more_nodes: EQ %jumpi(no_more_nodes) // stack: key, root_ptr, node_ptr_ptr, retdest PUSH after_smt_read DUP2 -global before_split_key: %split_key -global after_split_key: // stack: k0, k1, k2, k3, after_smt_read, key, root_ptr, node_ptr_ptr, retdest PUSH 0 DUP8 // stack: root_ptr, level, k0, k1, k2, k3, after_smt_read, key, root_ptr, node_ptr_ptr, retdest %jump(smt_read) after_smt_read: -global debug_after_smt_read: //stack: trie_value_ptr_ptr, key, root_ptr, node_ptr_ptr, retdest DUP4 %add_const(2) // Get the initial value diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm index 385903fe4..90f59af37 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/type2/state_linked_list.asm @@ -281,9 +281,7 @@ global search_key: // stack: key, retdest PROVER_INPUT(linked_list::search_state) // stack: pred_ptr/4, key, retdest -global debug_pred_ptr_p_4: %get_valid_state_ptr -global debug_pred_ptr: // stack: pred_ptr, key, retdest DUP1 @@ -301,7 +299,6 @@ global debug_pred_ptr: // stack: pred_key, pred_ptr, key, retdest // If we are here we know that addr <= pred_addr. But this is only possible if pred_addr == addr. DUP3 -global debug_fail_1: %assert_eq // stack: pred_ptr, key, retdest // Check that this is not a deleted node @@ -310,8 +307,6 @@ global debug_fail_1: MLOAD_GENERAL %jump_neq_const(@U256_MAX, key_found) // The key is not in the list. - -global debug_fail_2: PANIC global key_found: @@ -324,10 +319,8 @@ global key_found: JUMP key_not_found: -global debug_key_not_found: // stack: pred_key, pred_ptr, key, retdest %stack (pred_key, pred_ptr, key, retdest) -> (retdest, 0) -global debug_o_margot: JUMP %macro search_key diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 57dc8368c..621b595b7 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -110,7 +110,6 @@ global hash_initial_tries: // stack: trie_data_full_len // Check that the trie data length is correct. %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) -global debug_el_size: %assert_eq global start_txns: @@ -187,7 +186,6 @@ global perform_final_checks: // stack: cum_gas, txn_counter, num_nibbles, txn_nb // Check that we end up with the correct `cum_gas`, `txn_nb` and bloom filter. %mload_global_metadata(@GLOBAL_METADATA_BLOCK_GAS_USED_AFTER) -global debug_gas_error: %assert_eq DUP3 %mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_AFTER) %assert_eq @@ -220,7 +218,6 @@ global check_state_trie: %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) PROVER_INPUT(trie_ptr::trie_data_size) -global debug_storing_trie_data_size: %mstore_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) // stack: trie_data_len @@ -241,11 +238,9 @@ global debug_storing_trie_data_size: // stack: init_state_hash, trie_data_len // Check that the initial trie is correct. %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_BEFORE) -global debug_check_initial_trie: %assert_eq // Check that the stored trie data length is correct. %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) -global debug_trie_data_length: %assert_eq // We set a dummy value as an initial trie data length, @@ -266,7 +261,6 @@ global check_final_state_trie: } %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) -global debug_final_trie_hash: %assert_eq // We don't need the trie data length here. POP diff --git a/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm b/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm index 7b0cf0f7a..d2148de91 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/memory/syscalls.asm @@ -119,7 +119,6 @@ calldataload_large_offset: codecopy_within_bounds: -global debug_codecopy_withing_bounds: // stack: total_size, segment, src_ctx, kexit_info, dest_offset, offset, size POP // stack: segment, src_ctx, kexit_info, dest_offset, offset, size @@ -142,7 +141,6 @@ wcopy_within_bounds: %jump(memcpy_bytes) wcopy_empty: -global debug_wcopy_empty: // stack: Gverylow, kexit_info, dest_offset, offset, size %charge_gas %stack (kexit_info, dest_offset, offset, size) -> (kexit_info) @@ -150,7 +148,6 @@ global debug_wcopy_empty: codecopy_large_offset: -global codecopy_large_offset: // stack: total_size, src_ctx, kexit_info, dest_offset, offset, size POP // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. @@ -162,7 +159,6 @@ global codecopy_large_offset: %jump(memset) wcopy_large_offset: -global wcopy_large_offset: // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. // stack: kexit_info, dest_offset, offset, size GET_CONTEXT @@ -172,7 +168,6 @@ global wcopy_large_offset: %jump(memset) codecopy_after: -global codecopy_after: // stack: src_ctx, kexit_info DUP1 GET_CONTEXT // stack: ctx, src_ctx, src_ctx, kexit_info @@ -186,13 +181,11 @@ global codecopy_after: EXIT_KERNEL codecopy_no_prune: -global codecopy_no_prune: // stack: src_ctx, kexit_info POP EXIT_KERNEL wcopy_after: -global wcopy_after: // stack: kexit_info EXIT_KERNEL 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 36c7048f2..31fa192fa 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 @@ -150,7 +150,6 @@ global encode_txn: %build_kernel_address SWAP1 // stack: DST, SRC, txn_rlp_len, txn_rlp_len, rlp_addr, new_len, retdest -global debug_por_aca_se_copian_lost_bits: %memcpy_bytes ADD // stack new_rlp_addr, new_len, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm index 31934afaf..620db38dc 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/read.asm @@ -38,7 +38,6 @@ global smt_read: PANIC smt_read_hash: -global debug_smt_read_hash: // stack: node_type, node_payload_ptr, level, ks, retdest POP // stack: node_payload_ptr, level, ks, retdest @@ -48,12 +47,10 @@ global debug_smt_read_hash: PANIC // Trying to read a non-empty hash node. Should never happen. smt_read_empty: -global debug_smt_read_empty: %stack (level, k0, k1, k2, k3, retdest) -> (retdest, 0) JUMP smt_read_internal: -global debug_smt_read_internal: // stack: node_type, node_payload_ptr, level, ks, retdest POP // stack: node_payload_ptr, level, ks, retdest @@ -65,30 +62,25 @@ global debug_smt_read_internal: DUP1 %eq_const(3) %jumpi(smt_read_internal_3) PANIC smt_read_internal_0: -global debug_smt_read_internal_0: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k0, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk0, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, newk0, k1, k2, k3 ) %jump(smt_read_internal_contd) smt_read_internal_1: -global debug_smt_read_internal_1: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k1, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk1, node_payload_ptr, level , k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, newk1, k2, k3 ) %jump(smt_read_internal_contd) smt_read_internal_2: -global debug_smt_read_internal_2: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k2, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk2, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, newk2, k3 ) %jump(smt_read_internal_contd) smt_read_internal_3: -global debug_smt_read_internal_3: %stack (level_mod_4, node_payload_ptr, level, k0, k1, k2, k3 ) -> (k3, node_payload_ptr, level, k0, k1, k2, k3 ) %pop_bit %stack (bit, newk3, node_payload_ptr, level, k0, k1, k2, k3 ) -> (bit, node_payload_ptr, level, k0, k1, k2, newk3 ) smt_read_internal_contd: -global debug_smt_read_contd: // stack: bit, node_payload_ptr, level, k0, k1, k2, k3, retdest ADD // stack: child_ptr_ptr, level, k0, k1, k2, k3, retdest @@ -99,7 +91,6 @@ global debug_smt_read_contd: %jump(smt_read) smt_read_leaf: -global debug_smt_read_leaf: // stack: node_payload_ptr, level, ks, retdest DUP1 %mload_trie_data // stack: rem_key, node_payload_ptr, level, ks, retdest @@ -109,10 +100,8 @@ global debug_smt_read_leaf: %stack (value_ptr, rem_key, level, k0, k1, k2, k3) -> (k0, k1, k2, k3, rem_key, value_ptr) %combine_key // stack: this_rem_key, rem_key, value_ptr, retdest -global debug_pffff: EQ %jumpi(smt_read_existing_leaf) smt_read_non_existing_leaf: -global debug_smt_read_non_existing_leaf: %stack (value_ptr, retdest) -> (retdest, 0) JUMP 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 1a5140760..2098c6150 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/common_decoding.asm @@ -198,7 +198,6 @@ sk_loop: DUP2 DUP2 EQ %jumpi(end_sk) // stack: rlp_addr, sk_end_rlp_addr, addr, end_rlp_addr %decode_rlp_scalar // Storage key // TODO: Should panic when key is not 32 bytes? -global debug_todo_is_this_a_key_or_a_slot: %stack (rlp_addr, key, sk_end_rlp_addr, addr, end_rlp_addr) -> (addr, key, sk_loop_contd, rlp_addr, sk_end_rlp_addr, addr, end_rlp_addr) %jump(insert_accessed_storage_keys_with_original_value) @@ -231,7 +230,6 @@ insert_accessed_storage_keys_with_original_value: after_read: %stack (value, addr, key, retdest) -> (addr, key, value, retdest) %insert_accessed_storage_keys -global debug_si_por_aca: // stack: cold_access, value_ptr, value, retdest SWAP2 // stack: value, value_ptr, cold_access, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm index e754b77a9..ff7610f6d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm @@ -31,7 +31,6 @@ global process_type_0_txn: %decode_and_store_gas_limit %decode_and_store_to %decode_and_store_value -global debug_before_storing_txn_field_data_len: %decode_and_store_data // stack: rlp_addr, nonce_addr, retdest DUP1 diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 21a88e0a4..6189e8563 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -477,7 +477,6 @@ pub mod cancun_constants { pub const BEACON_ROOTS_CONTRACT_CODE_HASH: [u8; 32] = hex!("f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c"); - // #[cfg(feature = "eth_mainnet")] pub const BEACON_ROOTS_ACCOUNT: MptAccountRlp = MptAccountRlp { nonce: U256::zero(), balance: U256::zero(), @@ -541,7 +540,6 @@ pub mod global_exit_root { pub const GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH: [u8; 32] = hex!("6bec2bf64f7e824109f6ed55f77dd7665801d6195e461666ad6a5342a9f6daf5"); - // #[cfg(feature = "eth_mainnet")] pub const GLOBAL_EXIT_ROOT_ACCOUNT: MptAccountRlp = MptAccountRlp { nonce: U256::zero(), balance: U256::zero(), diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 51232b533..e5e659b8d 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -318,13 +318,6 @@ impl Interpreter { .as_smt() .to_vec(), ), - /* match &tries.state_trie.state { - * Either::Left(mpt) => - * h2u(mpt.state_trie().hash()), - * Either::Right(smt) => - * hash_serialize_u256(&smt. - * as_smt().to_vec()), - * }, */ ), ( GlobalMetadata::TransactionTrieRootDigestBefore, diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index f433e51f9..e84e28be9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -11,7 +11,6 @@ use mpt_trie::partial_trie::{HashedPartialTrie, Node, PartialTrie}; use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::hash::hash_types::RichField; use rand::{thread_rng, Rng}; -// #[cfg(feature = "cdk_erigon")] use smt_trie::code::hash_bytecode_u256; use crate::cpu::kernel::aggregator::KERNEL; @@ -162,14 +161,9 @@ pub(crate) fn prepare_interpreter( let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; let mut state_trie: HashedPartialTrie = HashedPartialTrie::from(Node::Empty); let trie_inputs = TrieInputs { - // #[cfg(feature = "eth_mainnet")] - // state_trie: HashedPartialTrie::from(Node::Empty), - // #[cfg(feature = "cdk_erigon")] state_trie: StateWorld::default(), transactions_trie: HashedPartialTrie::from(Node::Empty), receipts_trie: HashedPartialTrie::from(Node::Empty), - // #[cfg(feature = "eth_mainnet")] - // storage_tries: vec![], }; initialize_mpts(interpreter, &trie_inputs); @@ -270,19 +264,7 @@ pub(crate) fn prepare_interpreter( Ok(()) } -// // Test account with a given code hash. -// #[cfg(feature = "eth_mainnet")] -// fn test_account(code: &[u8]) -> MptAccountRlp { -// MptAccountRlp { -// nonce: U256::from(1111), -// balance: U256::from(2222), -// storage_root: HashedPartialTrie::from(Node::Empty).hash(), -// code_hash: keccak(code), -// } -// } - // Test account with a given code hash. -// #[cfg(feature = "eth_mainnet")] fn test_account(code: &[u8]) -> EitherRlp { if cfg!(feature = "eth_mainnet") { EitherRlp { @@ -305,17 +287,6 @@ fn test_account(code: &[u8]) -> EitherRlp { } } -// // Test account with a given code hash. -// #[cfg(feature = "cdk_erigon")] -// fn test_account(code: &[u8]) -> SmtAccountRlp { -// SmtAccountRlp { -// nonce: U256::from(1111), -// balance: U256::from(2222), -// code_hash: hash_bytecode_u256(code.to_vec()), -// code_length: code.len().into(), -// } -// } - fn random_code() -> Vec { let mut rng = thread_rng(); let num_bytes = rng.gen_range(0..1000); @@ -353,16 +324,6 @@ fn test_extcodesize() -> Result<()> { code.clone(), )]) }; - // #[cfg(feature = "eth_mainnet")] - // { - // interpreter.generation_state.inputs.contract_code = - // HashMap::from([(keccak(&code), code.clone())]); - // } - // #[cfg(feature = "cdk_erigon")] - // { - // interpreter.generation_state.inputs.contract_code = - // HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); - // } interpreter.run()?; @@ -444,16 +405,6 @@ fn test_extcodecopy() -> Result<()> { code.clone(), )]) }; - // #[cfg(feature = "eth_mainnet")] - // { - // interpreter.generation_state.inputs.contract_code = - // HashMap::from([(keccak(&code), code.clone())]); - // } - // #[cfg(feature = "cdk_erigon")] - // { - // interpreter.generation_state.inputs.contract_code = - // HashMap::from([(hash_bytecode_u256(code.clone()), code.clone())]); - // } interpreter.run()?; @@ -581,7 +532,6 @@ fn sstore() -> Result<()> { state_trie, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - // storage_tries: vec![(addr_hashed, Node::Empty.into())], }; let initial_stack = vec![]; @@ -701,7 +651,6 @@ fn sload() -> Result<()> { state_trie, transactions_trie: Node::Empty.into(), receipts_trie: Node::Empty.into(), - // storage_tries: vec![(addr_hashed, Node::Empty.into())], }; let initial_stack = vec![]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/balance.rs b/evm_arithmetization/src/cpu/kernel/tests/balance.rs index ec983fd14..baaea6302 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/balance.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/balance.rs @@ -14,7 +14,6 @@ use crate::generation::mpt::SmtAccountRlp; use crate::Node; // Test account with a given code hash. -// #[cfg(feature = "eth_mainnet")] fn test_account(balance: U256) -> EitherRlp { if cfg!(feature = "eth_mainnet") { EitherRlp { @@ -37,19 +36,6 @@ fn test_account(balance: U256) -> EitherRlp { } } -// // Test account with a given code hash. -// #[cfg(feature = "cdk_erigon")] -// fn test_account(balance: U256) -> SmtAccountRlp { -// use smt_trie::code::hash_bytecode_u256; - -// SmtAccountRlp { -// nonce: U256::from(1111), -// balance, -// code_hash: hash_bytecode_u256(vec![0x01, 0x00]), -// code_length: 2.into(), -// } -// } - #[test] fn test_balance() -> Result<()> { let mut rng = thread_rng(); diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs index 36c48ad4b..25eb3e3c5 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -50,13 +50,11 @@ fn test_init_exc_stop() { ..Default::default() }; - // #[cfg(feature = "cdk_erigon")] let state_trie_before = StateWorld::default(); let transactions_trie = HashedPartialTrie::from(Node::Empty); let receipts_trie = HashedPartialTrie::from(Node::Empty); - // #[cfg(feature = "cdk_erigon")] let mut expected_state_trie_after = StateWorld::default(); #[cfg(feature = "eth_mainnet")] let (state_trie_before_hashed, storage_tries) = @@ -113,10 +111,7 @@ fn test_init_exc_stop() { } let mut contract_code = HashMap::new(); - // #[cfg(feature = "eth_mainnet")] - // contract_code.insert(keccak(vec![]), vec![]); - // #[cfg(feature = "cdk_erigon")] - // contract_code.insert(hash_bytecode_u256(vec![]), vec![]); + let contract_hash = if cfg!(feature = "eth_mainnet") { Either::Left(keccak(vec![])) } else { @@ -129,10 +124,6 @@ fn test_init_exc_stop() { Either::Right(type2world) => H256::from_uint(&hashout2u(type2world.as_smt().root)), }; let trie_roots_after = TrieRoots { - // #[cfg(feature = "cdk_erigon")] - // state_root: H256::from_uint(&hashout2u(expected_state_trie_after.root)), - // #[cfg(feature = "eth_mainnet")] - // state_root: expected_state_trie_after.hash(), state_root, transactions_root: transactions_trie.hash(), receipts_root: receipts_trie.hash(), @@ -146,8 +137,6 @@ fn test_init_exc_stop() { state_trie: state_trie_before, transactions_trie, receipts_trie, - // #[cfg(feature = "eth_mainnet")] - // storage_tries, }, trie_roots_after, contract_code, diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs index 57ba15b88..f65171420 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs @@ -100,7 +100,6 @@ fn test_state_trie( state_trie: state_world, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let mpt_delete = KERNEL.global_labels["mpt_delete"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs index 884375d77..a4278d756 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs @@ -20,7 +20,6 @@ fn mpt_hash_empty() -> Result<()> { state_trie: Default::default(), transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; test_state_trie(trie_inputs) @@ -40,7 +39,6 @@ fn mpt_hash_empty_branch() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; test_state_trie(trie_inputs) } @@ -54,7 +52,6 @@ fn mpt_hash_hash() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; test_state_trie(trie_inputs) @@ -73,7 +70,6 @@ fn mpt_hash_leaf() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; test_state_trie(trie_inputs) } @@ -85,7 +81,6 @@ fn mpt_hash_extension_to_leaf() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; test_state_trie(trie_inputs) } @@ -112,7 +107,6 @@ fn mpt_hash_branch_to_leaf() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; test_state_trie(trie_inputs) diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs index b72967520..a82170c02 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs @@ -187,7 +187,6 @@ fn test_state_trie( state_trie: state_trie_inputs, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs index 5f8eeb973..dd261b4a9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs @@ -27,7 +27,6 @@ fn load_all_mpts_empty() -> Result<()> { state_trie: Default::default(), transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let initial_stack = vec![]; @@ -67,7 +66,6 @@ fn load_all_mpts_leaf() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let initial_stack = vec![]; @@ -130,7 +128,6 @@ fn load_all_mpts_hash() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let initial_stack = vec![]; @@ -178,7 +175,6 @@ fn load_all_mpts_empty_branch() -> Result<()> { state_trie, transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let initial_stack = vec![]; @@ -230,7 +226,6 @@ fn load_all_mpts_ext_to_leaf() -> Result<()> { state_trie: get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())), transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let initial_stack = vec![]; @@ -282,7 +277,6 @@ fn load_mpt_txn_trie() -> Result<()> { value: txn.clone(), }), receipts_trie: Default::default(), - // storage_tries: vec![], }; let initial_stack = vec![]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 637aea902..40c76bc66 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -43,7 +43,6 @@ pub(crate) fn nibbles_count>(v: T, count: usize) -> Nibbles { } } -// #[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_1_empty_storage() -> EitherRlp { if cfg!(feature = "cdk_erigon") { EitherRlp { @@ -68,44 +67,13 @@ pub(crate) fn test_account_1_empty_storage() -> EitherRlp { #[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_1() -> MptAccountRlp { - // if cfg!(feature = "cdk_erigon") { - // EitherRlp { - // account_rlp: Either::Right(SmtAccountRlp { - // nonce: U256::from(1111), - // balance: U256::from(2222), - // code_hash: U256::from(4444), - // code_length: 0.into(), - // }), - // } - // } else { MptAccountRlp { nonce: U256::from(1111), balance: U256::from(2222), storage_root: H256::from_uint(&U256::from(3333)), code_hash: H256::from_uint(&U256::from(4444)), } - - // } } -// #[cfg(feature = "cdk_erigon")] -// pub(crate) fn test_account_1() -> Box { -// Box::new(SmtAccountRlp { -// nonce: U256::from(1111), -// balance: U256::from(2222), -// code_hash: U256::from(4444), -// code_length: 0.into(), -// }) -// } - -// #[cfg(feature = "cdk_erigon")] -// pub(crate) fn test_account_1_empty_storage() -> Box { -// Box::new(SmtAccountRlp { -// nonce: U256::from(1111), -// balance: U256::from(2222), -// code_hash: U256::from(4444), -// code_length: 0.into(), -// }) -// } #[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_1_rlp() -> Vec { @@ -118,16 +86,6 @@ pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { #[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_2() -> MptAccountRlp { - // if cfg!(feature = "cdk_erigon") { - // EitherRlp { - // account_rlp: Either::Right(SmtAccountRlp { - // nonce: U256::from(5555), - // balance: U256::from(6666), - // code_hash: U256::from(8888), - // code_length: 0.into(), - // }), - // } - // } else { MptAccountRlp { nonce: U256::from(5555), balance: U256::from(6666), @@ -135,19 +93,6 @@ pub(crate) fn test_account_2() -> MptAccountRlp { code_hash: H256::from_uint(&U256::from(8888)), } } -// } - -// #[cfg(feature = "cdk_erigon")] -// pub(crate) fn test_account_2() -> Box { -// use crate::generation::mpt::SmtAccountRlp; - -// Box::new(SmtAccountRlp { -// nonce: U256::from(5555), -// balance: U256::from(6666), -// code_hash: U256::from(8888), -// code_length: 0.into(), -// }) -// } #[cfg(feature = "eth_mainnet")] pub(crate) fn test_account_2_rlp() -> Vec { diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs index fe3ff467b..9d32e3195 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs @@ -17,7 +17,6 @@ fn mpt_read() -> Result<()> { state_trie: get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())), transactions_trie: Default::default(), receipts_trie: Default::default(), - // storage_tries: vec![], }; let mpt_read = KERNEL.global_labels["mpt_read"]; diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index ddcc191ad..7f1cbc8aa 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -122,9 +122,6 @@ pub struct GenerationInputs { /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. - // #[cfg(feature = "eth_mainnet")] - // pub contract_code: HashMap>, - // #[cfg(feature = "cdk_erigon")] pub contract_code: HashMap, Vec>, /// Information contained in the block header. @@ -177,9 +174,6 @@ pub struct TrimmedGenerationInputs { /// Mapping between smart contract code hashes and the contract byte code. /// All account smart contracts that are invoked will have an entry present. - // #[cfg(feature = "eth_mainnet")] - // pub contract_code: HashMap>, - // #[cfg(feature = "cdk_erigon")] pub contract_code: HashMap, Vec>, /// Information contained in the block header. @@ -201,10 +195,11 @@ type SmtTrie = smt_trie::smt::Smt; pub struct TrieInputs { /// A partial version of the state trie prior to these transactions. It /// should include all nodes that will be accessed by these + /// transactions. In "eth_mainnet", it also contains the storage trie prior + /// to these transactions (including all storage tries, and nodes therein, + /// that will be accessed by these transactions). In "eth_mainnet", it also + /// includes a partial version of each storage trie prior to these /// transactions. - // #[cfg(feature = "eth_mainnet")] - // pub state_trie: HashedPartialTrie, - // #[cfg(feature = "cdk_erigon")] pub state_trie: StateWorld, /// A partial version of the transaction trie prior to these transactions. @@ -216,38 +211,18 @@ pub struct TrieInputs { /// should include all nodes that will be accessed by these /// transactions. pub receipts_trie: HashedPartialTrie, - // /// A partial version of each storage trie prior to these transactions. It - // /// should include all storage tries, and nodes therein, that will be - // /// accessed by these transactions. - // #[cfg(feature = "eth_mainnet")] - // pub storage_tries: Vec<(H256, HashedPartialTrie)>, } #[derive(Clone, Debug, Deserialize, Serialize, Default)] pub struct TrimmedTrieInputs { /// A partial version of the state trie prior to these transactions. It /// should include all nodes that will be accessed by these - /// transactions. - // #[cfg(feature = "eth_mainnet")] - // pub state_trie: HashedPartialTrie, - // #[cfg(feature = "cdk_erigon")] + /// transactions. In "eth_mainnet", it also contains the storage trie prior + /// to these transactions. pub state_trie: StateWorld, - // /// A partial version of each storage trie prior to these transactions. It - // /// should include all storage tries, and nodes therein, that will be - // /// accessed by these transactions. - // #[cfg(feature = "eth_mainnet")] - // pub storage_tries: Vec<(H256, HashedPartialTrie)>, } impl TrieInputs { - // #[cfg(feature = "eth_mainnet")] - // pub(crate) fn trim(&self) -> TrimmedTrieInputs { - // TrimmedTrieInputs { - // state_trie: self.state_trie.clone(), - // // storage_tries: self.storage_tries.clone(), - // } - // } - // #[cfg(feature = "cdk_erigon")] pub(crate) fn trim(&self) -> TrimmedTrieInputs { TrimmedTrieInputs { state_trie: self.state_trie.clone(), @@ -266,13 +241,6 @@ impl GenerationInputs { .map(|tx_bytes| keccak(&tx_bytes[..])) .collect(); - // let mut state_root = H256::zero(); - // #[cfg(feature = "eth_mainnet")] - // { - // state_root = self.tries.state_trie.hash(); - // } - // #[cfg(feature = "cdk_erigon")] - // { let state_root = match &self.tries.state_trie.state { Either::Left(trie) => trie.state_trie().hash(), Either::Right(trie) => { @@ -280,7 +248,6 @@ impl GenerationInputs { H256::from_uint(&hash_serialize_u256(&smt_data).into()) } }; - // } TrimmedGenerationInputs { trimmed_tries: self.tries.trim(), diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 179ebeff7..b44736906 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -53,9 +53,6 @@ pub struct MptAccountRlp { } impl AccountRlp for MptAccountRlp { - // fn as_any(&self) -> &dyn Any { - // self - // } fn get_nonce(&self) -> U256 { self.nonce } @@ -88,9 +85,6 @@ pub struct SmtAccountRlp { } impl AccountRlp for SmtAccountRlp { - // fn as_any(&self) -> &dyn Any { - // self - // } fn get_nonce(&self) -> U256 { self.nonce } @@ -122,7 +116,6 @@ pub trait AccountRlp: Any { fn get_code_hash(&self) -> CodeHashType; fn get_code_hash_u256(&self) -> U256; fn rlp_encode(&self) -> BytesMut; - // fn as_any(&self) -> &dyn Any; } pub struct EitherRlp { @@ -416,7 +409,6 @@ where } } -// #[cfg(feature = "eth_mainnet")] fn load_state_trie( trie: &HashedPartialTrie, key: Nibbles, @@ -772,7 +764,6 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( Ok((state_leaves, storage_leaves, trie_data)) } -// #[cfg(feature = "eth_mainnet")] pub(crate) fn load_state_mpt( trie_inputs: &TrimmedTrieInputs, trie_data: &mut Vec>, diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index b5790c8e0..b54b9d40c 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -17,7 +17,6 @@ use super::linked_list::testing::{LinkedList, ADDRESSES_ACCESS_LIST_LEN}; #[cfg(feature = "eth_mainnet")] use super::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use super::linked_list::{AccessLinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD}; -// #[cfg(feature = "eth_mainnet")] use super::mpt::load_state_mpt; use crate::cpu::kernel::cancun_constants::KZG_VERSIONED_HASH; use crate::cpu::kernel::constants::cancun_constants::{ @@ -101,22 +100,7 @@ impl GenerationState { .map_or_else( || { let mut new_content = self.memory.get_preinit_memory(Segment::TrieData); - // let mut n = Err(ProgramError::ProverInputError( - // ProverInputError::InvalidInput, - // )); - // #[cfg(feature = "eth_mainnet")] - // { - // n = load_state_mpt(&self.inputs.trimmed_tries, &mut new_content); - - // self.memory.insert_preinitialized_segment( - // Segment::TrieData, - // crate::witness::memory::MemorySegmentState { - // content: new_content, - // }, - // ); - // } - // #[cfg(feature = "cdk_erigon")] - // { + let n = if cfg!(feature = "cdk_erigon") { Ok(new_content.len()) } else { @@ -153,35 +137,19 @@ impl GenerationState { .map(U256::from), "txn" => Ok(U256::from(self.trie_root_ptrs.txn_root_ptr)), "receipt" => Ok(U256::from(self.trie_root_ptrs.receipt_root_ptr)), - "trie_data_size" => { - // println!( - // "length {}", - // self.memory - // .preinitialized_segments - // .get(&Segment::TrieData) - // .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) - // .content - // .len() - // .max( - // self.memory.contexts[0].segments[Segment::TrieData.unscale()] - // .content - // .len(), - // ) - // ); - Ok(self - .memory - .preinitialized_segments - .get(&Segment::TrieData) - .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) - .content - .len() - .max( - self.memory.contexts[0].segments[Segment::TrieData.unscale()] - .content - .len(), - ) - .into()) - } + "trie_data_size" => Ok(self + .memory + .preinitialized_segments + .get(&Segment::TrieData) + .unwrap_or(&crate::witness::memory::MemorySegmentState { content: vec![] }) + .content + .len() + .max( + self.memory.contexts[0].segments[Segment::TrieData.unscale()] + .content + .len(), + ) + .into()), _ => Err(ProgramError::ProverInputError(InvalidInput)), } @@ -266,25 +234,6 @@ impl GenerationState { /// Initializes the code segment of the given context with the code /// corresponding to the provided hash. /// Returns the length of the code. - // #[cfg(feature = "eth_mainnet")] - // fn run_account_code(&mut self) -> Result { - // // stack: codehash, ctx, ... - // let codehash = stack_peek(self, 0)?; - // let context = stack_peek(self, 1)? >> CONTEXT_SCALING_FACTOR; - // let context = u256_to_usize(context)?; - // let mut address = MemoryAddress::new(context, Segment::Code, 0); - // let code = self - // .inputs - // .contract_code - // .get(&H256::from_uint(&codehash)) - // .ok_or(ProgramError::ProverInputError(CodeHashNotFound))?; - // for &byte in code { - // self.memory.set(address, byte.into()); - // address.increment(); - // } - // Ok(code.len().into()) - // } - // #[cfg(feature = "cdk_erigon")] fn run_account_code(&mut self) -> Result { // stack: codehash, ctx, ... diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index ddd34670a..444b9c59e 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -8,7 +8,6 @@ use itertools::Itertools; use keccak_hash::keccak; use log::Level; use plonky2::hash::hash_types::RichField; -// #[cfg(feature = "cdk_erigon")] use smt_trie::code::hash_bytecode_u256; use super::mpt::TrieRootPtrs; @@ -426,7 +425,6 @@ impl GenerationState { load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); let receipt_root_ptr = load_receipts_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); - // println!("trie data length after init {}", trie_data.len()); self.memory.insert_preinitialized_segment( Segment::TrieData, crate::witness::memory::MemorySegmentState { content: trie_data }, @@ -606,13 +604,6 @@ impl GenerationState { Either::Left(H256::from_uint(&tip_u256)) }; self.observe_contract(tip_either)?; - // #[cfg(feature = "eth_mainnet")] - // { - // let tip_h256 = H256::from_uint(&tip_u256); - // self.observe_contract(tip_h256)?; - // } - // #[cfg(feature = "cdk_erigon")] - // self.observe_contract(tip_u256)?; } Ok(()) @@ -628,35 +619,6 @@ impl GenerationState { /// Observe the given code hash and store the associated code. /// When called, the code corresponding to `codehash` should be stored in /// the return data. - // #[cfg(feature = "eth_mainnet")] - // pub(crate) fn observe_contract( - // &mut self, - // codehash: Either, - // ) -> Result<(), ProgramError> { - // if self.inputs.contract_code.contains_key(&codehash) { - // return Ok(()); // Return early if the code hash has already been - // // observed. - // } - - // let ctx = self.registers.context; - // let returndata_offset = ContextMetadata::ReturndataSize.unscale(); - // let returndata_size_addr = - // MemoryAddress::new(ctx, Segment::ContextMetadata, returndata_offset); - // let returndata_size = - // u256_to_usize(self.memory.get_with_init(returndata_size_addr))?; - // let code = - // self.memory.contexts[ctx].segments[Segment::Returndata.unscale()].content - // [..returndata_size] - // .iter() - // .map(|x| x.unwrap_or_default().low_u32() as u8) - // .collect::>(); - // debug_assert_eq!(keccak(&code), codehash); - - // self.inputs.contract_code.insert(codehash, code); - - // Ok(()) - // } - // #[cfg(feature = "cdk_erigon")] pub(crate) fn observe_contract( &mut self, codehash: Either, diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 7d42266bf..698c23934 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -356,7 +356,6 @@ pub fn check_abort_signal(abort_signal: Option>) -> Result<()> { pub(crate) fn features_check(inputs: &TrimmedGenerationInputs) { if !cfg!(feature = "eth_mainnet") { assert!(inputs.block_metadata.parent_beacon_block_root.is_zero()); - println!("block blob gas used = {:?}", inputs.block_metadata.block_blob_gas_used); assert!(inputs.block_metadata.block_blob_gas_used.is_zero()); assert!(inputs.block_metadata.block_excess_blob_gas.is_zero()); } diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index 283a89d62..8a3a80d3c 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -198,20 +198,10 @@ fn empty_payload() -> Result { // Initialize an empty state trie and storage tries let state_trie_before = HashedPartialTrie::from(crate::Node::Empty); - // #[cfg(feature = "eth_mainnet")] - // let storage_tries = Vec::new(); + let checkpoint_state_trie_root = state_trie_before.hash(); // Prepare the tries without any transactions or receipts - // #[cfg(feature = "eth_mainnet")] - // let tries_before = TrieInputs { - // state_trie: state_trie_before.clone(), - // storage_tries: storage_tries.clone(), - // transactions_trie: HashedPartialTrie::from(crate::Node::Empty), - // receipts_trie: HashedPartialTrie::from(crate::Node::Empty), - // }; - - // #[cfg(feature = "cdk_erigon")] let tries_before = TrieInputs { state_trie: StateWorld::default(), transactions_trie: HashedPartialTrie::from(crate::Node::Empty), diff --git a/evm_arithmetization/src/witness/operation.rs b/evm_arithmetization/src/witness/operation.rs index 76813d5a5..9af559c8a 100644 --- a/evm_arithmetization/src/witness/operation.rs +++ b/evm_arithmetization/src/witness/operation.rs @@ -248,8 +248,6 @@ pub(crate) fn generate_poseidon_general>( len: input.len(), }); - log::debug!("pushign poseding op = {:?}", poseidon_op); - let hash = hashout2u(poseidon_hash_padded_byte_vec(input.clone())); push_no_write(generation_state, hash); diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index cb4da38e0..d47f56ab7 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -314,16 +314,6 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o state.get_generation_state().stack(), ), ); - // if KERNEL.offset_name(pc) == "insert_all_initial_nodes" { - // let mem = state - // .get_generation_state() - // .memory - // .get_preinit_memory(Segment::AccountsLinkedList); - // log::debug!( - // "state linked list = {:?}", - // StateLinkedList::from_mem_and_segment(&mem, - // Segment::AccountsLinkedList) ); - // } #[cfg(test)] if KERNEL.offset_name(pc) == "smt_hash_state" || KERNEL.offset_name(pc) == "sys_sstore" { @@ -355,27 +345,6 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o .collect::>() ); } - // state.log( - // level, - // format!( - // "state memory = {:?}", - // state - // .get_generation_state() - // .memory - // .get_preinit_memory(Segment::AccountsLinkedList), - // ), - // ); - // state.log( - // level, - // format!( - // "smt = {}", - // state - // .get_generation_state() - // .inputs - // .trimmed_tries - // .state_trie - // ), - // ); assert!( pc < KERNEL.code.len(), diff --git a/evm_arithmetization/src/world/world.rs b/evm_arithmetization/src/world/world.rs index a945fa9dc..79972a393 100644 --- a/evm_arithmetization/src/world/world.rs +++ b/evm_arithmetization/src/world/world.rs @@ -162,10 +162,6 @@ impl Type1World { .iter() .map(|(key, value)| (*key, value.as_hashed_partial_trie())) .collect::>() - // .self - // .storage - // .get_mut(&keccak_hash::keccak(address)) - // .context("no such storage") } fn on_storage( &mut self, diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index cb7d68f51..9bd89585e 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -366,35 +366,6 @@ fn bloom() -> [U256; 8] { bloom.try_into().unwrap() } -// fn set_account( -// smt: &mut Smt, -// addr: Address, -// account: &SmtAccountRlp, -// storage: &HashMap, -// ) { -// let key = key_balance(addr); -// log::debug!( -// "setting {:?} balance to {:?}, the key is {:?}", -// addr, -// account.balance, -// U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) -// ); -// smt.set(key_balance(addr), account.balance); -// smt.set(key_nonce(addr), account.nonce); -// log::debug!("account code {:?}", account.code_hash); -// smt.set(key_code(addr), account.code_hash); -// let key = key_code_length(addr); -// log::debug!( -// "setting {:?} code length, the key is {:?}", -// addr, -// U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) -// ); -// smt.set(key_code_length(addr), account.code_length); -// for (&k, &v) in storage { -// smt.set(key_storage(addr, k), v); -// } -// } - fn set_account( world: &mut StateWorld, addr: Address, diff --git a/smt_trie/src/code.rs b/smt_trie/src/code.rs index 49e3f6ffe..dd6b142b9 100644 --- a/smt_trie/src/code.rs +++ b/smt_trie/src/code.rs @@ -10,9 +10,6 @@ use crate::utils::hashout2u; pub fn hash_contract_bytecode(mut code: Vec) -> HashOut { poseidon_pad_byte_vec(&mut code); - // println!("code bytes = {:?}", code); - // println!("hash = {:?}", - // hashout2u(poseidon_hash_padded_byte_vec(code.clone()))); poseidon_hash_padded_byte_vec(code) } @@ -40,7 +37,6 @@ pub fn poseidon_hash_padded_byte_vec(bytes: Vec) -> HashOut { pub fn poseidon_pad_byte_vec(bytes: &mut Vec) { bytes.push(0x01); - // println!("code len = {:?}", bytes.len()); while bytes.len() % 56 != 0 { bytes.push(0x00); } From f8d3619a36f0c6350344b9fd2fe8accc7f77b000 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 5 Nov 2024 12:00:15 -0500 Subject: [PATCH 44/60] Fix MPT preinit --- .../src/cpu/kernel/interpreter.rs | 9 -- .../src/cpu/kernel/tests/account_code.rs | 98 ++++++++++--------- evm_arithmetization/src/generation/mpt.rs | 32 +++++- evm_arithmetization/src/generation/state.rs | 14 +-- 4 files changed, 84 insertions(+), 69 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index e5e659b8d..297664e8c 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -502,15 +502,6 @@ impl Interpreter { .set(MemoryAddress::new(0, Segment::RlpRaw, 0), 0x80.into()) } - /// Inserts a preinitialized segment, given as a [Segment], - /// into the `preinitialized_segments` memory field. - #[cfg(feature = "eth_mainnet")] - fn insert_preinitialized_segment(&mut self, segment: Segment, values: MemorySegmentState) { - self.generation_state - .memory - .insert_preinitialized_segment(segment, values); - } - pub(crate) fn is_preinitialized_segment(&self, segment: usize) -> bool { self.generation_state .memory diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index e84e28be9..3c424988c 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -21,7 +21,7 @@ use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; #[cfg(feature = "eth_mainnet")] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; -use crate::generation::mpt::{AccountRlp, EitherRlp, MptAccountRlp, SmtAccountRlp}; +use crate::generation::mpt::{load_state_mpt, AccountRlp, EitherRlp, MptAccountRlp, SmtAccountRlp}; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -33,18 +33,26 @@ pub(crate) fn initialize_mpts( interpreter: &mut Interpreter, trie_inputs: &TrieInputs, ) { + #[cfg(feature = "cdk_erigon")] + { + interpreter + .generation_state + .preinitialize_linked_lists(trie_inputs); + } + // Load all MPTs. #[cfg(feature = "eth_mainnet")] { - let (state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( - &mut interpreter - .generation_state - .state_pointers - .accounts_pointers, - &mut interpreter.generation_state.state_pointers.storage_pointers, - trie_inputs, - ) - .expect("Invalid MPT data for preinitialization"); + let (mut trie_root_ptrs, state_leaves, storage_leaves, trie_data) = + load_linked_lists_and_txn_and_receipt_mpts( + &mut interpreter + .generation_state + .state_pointers + .accounts_pointers, + &mut interpreter.generation_state.state_pointers.storage_pointers, + trie_inputs, + ) + .expect("Invalid MPT data for preinitialization"); interpreter.generation_state.memory.contexts[0].segments [Segment::AccountsLinkedList.unscale()] @@ -54,30 +62,38 @@ pub(crate) fn initialize_mpts( .content = storage_leaves; interpreter.generation_state.memory.contexts[0].segments[Segment::TrieData.unscale()] .content = trie_data.clone(); - // interpreter.generation_state.trie_root_ptrs = trie_root_ptrs.clone(); - - // if trie_root_ptrs.state_root_ptr.is_none() { - // trie_root_ptrs.state_root_ptr = Some( - // load_state_mpt( - // &trie_inputs.trim(), - // &mut interpreter.generation_state.memory.contexts[0].segments - // [Segment::TrieData.unscale()] - // .content, - // ) - // .expect("Invalid MPT data for preinitialization"), - // ); - // } - - // let mut to_set = vec![]; - // if let Some(state_root_ptr) = trie_root_ptrs.state_root_ptr { - // to_set.push((state_addr, state_root_ptr.into())); - // } - // to_set.extend([ - // (txn_addr, trie_root_ptrs.txn_root_ptr.into()), - // (receipts_addr, trie_root_ptrs.receipt_root_ptr.into()), - // ]); - - // interpreter.set_memory_multi_addresses(&to_set); + interpreter.generation_state.trie_root_ptrs = trie_root_ptrs.clone(); + + if trie_root_ptrs.state_root_ptr.is_none() { + trie_root_ptrs.state_root_ptr = Some( + load_state_mpt( + &trie_inputs.trim(), + &mut interpreter.generation_state.memory.contexts[0].segments + [Segment::TrieData.unscale()] + .content, + ) + .expect("Invalid MPT data for preinitialization"), + ); + } + + let state_addr = + MemoryAddress::new_bundle((GlobalMetadata::StateTrieRoot as usize).into()).unwrap(); + let txn_addr = + MemoryAddress::new_bundle((GlobalMetadata::TransactionTrieRoot as usize).into()) + .unwrap(); + let receipts_addr = + MemoryAddress::new_bundle((GlobalMetadata::ReceiptTrieRoot as usize).into()).unwrap(); + + let mut to_set = vec![]; + if let Some(state_root_ptr) = trie_root_ptrs.state_root_ptr { + to_set.push((state_addr, state_root_ptr.into())); + } + to_set.extend([ + (txn_addr, trie_root_ptrs.txn_root_ptr.into()), + (receipts_addr, trie_root_ptrs.receipt_root_ptr.into()), + ]); + + interpreter.set_memory_multi_addresses(&to_set); for (i, data) in trie_data.iter().enumerate() { let trie_addr = MemoryAddress::new(0, Segment::TrieData, i); @@ -88,13 +104,6 @@ pub(crate) fn initialize_mpts( } } - #[cfg(feature = "cdk_erigon")] - { - interpreter - .generation_state - .preinitialize_linked_lists(trie_inputs); - } - let accounts_len = Segment::AccountsLinkedList as usize + interpreter.generation_state.memory.contexts[0].segments [Segment::AccountsLinkedList.unscale()] @@ -141,13 +150,6 @@ pub(crate) fn initialize_mpts( (initial_accounts_len_addr, accounts_len.into()), (initial_storage_len_addr, storage_len.into()), ]); - - let _state_addr = - MemoryAddress::new_bundle((GlobalMetadata::StateTrieRoot as usize).into()).unwrap(); - let _txn_addr = - MemoryAddress::new_bundle((GlobalMetadata::TransactionTrieRoot as usize).into()).unwrap(); - let _receipts_addr = - MemoryAddress::new_bundle((GlobalMetadata::ReceiptTrieRoot as usize).into()).unwrap(); } // Stolen from `tests/mpt/insert.rs` diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index b44736906..d3a4ef27f 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -721,7 +721,12 @@ where /// - the vector of state trie leaves /// - the vector of storage trie leaves /// - the `TrieData` segment's memory content -type LinkedListsAndTrieData = (Vec>, Vec>, Vec>); +type LinkedListsAndTrieData = ( + TrieRootPtrs, + Vec>, + Vec>, + Vec>, +); #[cfg(feature = "eth_mainnet")] pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( @@ -738,7 +743,7 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( let mut trie_data = vec![Some(U256::zero())]; let mpt_state = match &trie_inputs.state_trie.state { Either::Left(type1world) => type1world, - Either::Right(_) => panic!("eth_mainnet expects MPTs."), + Either::Right(_) => unreachable!("eth_mainnet expects MPTs."), }; let storage_tries_by_state_key = mpt_state .get_storage() @@ -750,6 +755,14 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( }) .collect(); + let txn_root_ptr = load_mpt(&trie_inputs.transactions_trie, &mut trie_data, &|rlp| { + let mut parsed_txn = vec![U256::from(rlp.len())]; + parsed_txn.extend(rlp.iter().copied().map(U256::from)); + Ok(parsed_txn) + })?; + + let receipt_root_ptr = load_mpt(&trie_inputs.receipts_trie, &mut trie_data, &parse_receipts)?; + get_state_and_storage_leaves( &mpt_state.state_trie(), empty_nibbles(), @@ -761,7 +774,16 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( &storage_tries_by_state_key, )?; - Ok((state_leaves, storage_leaves, trie_data)) + Ok(( + TrieRootPtrs { + state_root_ptr: None, + txn_root_ptr, + receipt_root_ptr, + }, + state_leaves, + storage_leaves, + trie_data, + )) } pub(crate) fn load_state_mpt( @@ -778,12 +800,12 @@ pub(crate) fn load_state_mpt( (key, *storage_trie) }) .collect::>(), - Either::Right(_) => panic!("eth_mainnet expects an MPT."), + Either::Right(_) => unreachable!("eth_mainnet expects an MPT."), }; let mpt_trie = match &trie_inputs.state_trie.state { Either::Left(t) => t.state_trie(), - Either::Right(_) => panic!("eth_mainnet expects MPTs."), + Either::Right(_) => unreachable!("eth_mainnet expects MPTs."), }; load_state_trie( diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 538831c0e..56778fdf2 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -439,14 +439,14 @@ impl GenerationState { #[cfg(feature = "eth_mainnet")] fn preinitialize_linked_lists(&mut self, trie_inputs: &TrieInputs) { let generation_state = self.get_mut_generation_state(); - let (state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( - &mut generation_state.state_pointers.accounts_pointers, - &mut generation_state.state_pointers.storage_pointers, - trie_inputs, - ) - .expect("Invalid MPT data for preinitialization"); + let (_trie_root_ptrs, state_leaves, storage_leaves, trie_data) = + load_linked_lists_and_txn_and_receipt_mpts( + &mut generation_state.state_pointers.accounts_pointers, + &mut generation_state.state_pointers.storage_pointers, + trie_inputs, + ) + .expect("Invalid MPT data for preinitialization"); // TODO: REMOVE - println!("trie data len after linked lists {}", trie_data.len()); self.memory.insert_preinitialized_segment( Segment::AccountsLinkedList, crate::witness::memory::MemorySegmentState { From 76b78c9d96f6730944559a49b0c6565ca367746d Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 5 Nov 2024 15:40:03 -0500 Subject: [PATCH 45/60] Expand keys in tests --- evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index 40c76bc66..e9b11478e 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -118,6 +118,15 @@ pub(crate) fn extension_to_leaf(value: Vec) -> HashedPartialTrie { #[cfg(feature = "eth_mainnet")] pub(crate) fn get_state_world_no_storage(state_trie: HashedPartialTrie) -> StateWorld { + // `Type1World` expects full keys, so we manually expand the nibbles here. + + use mpt_trie::utils::TryFromIterator as _; + let state_trie = HashedPartialTrie::try_from_iter(state_trie.items().map(|(mut key, val)| { + key.count = 64; + (key, val) + })) + .expect("This should never fail"); + StateWorld { state: Either::Left( Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(), From 1a33ec4e9e40d554f077210d4736eeca1d4e43e3 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 5 Nov 2024 15:46:29 -0500 Subject: [PATCH 46/60] Fix --- evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs index dd261b4a9..2abbcfac9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs @@ -85,7 +85,7 @@ fn load_all_mpts_leaf() -> Result<()> { test_account_1().code_hash.into_uint(), // Values used for hashing. type_leaf, - 3.into(), + 64.into(), // should be 3 nibbles but keys are extended for `Type1World` 0xABC.into(), 9.into(), // value ptr test_account_1().nonce, @@ -246,11 +246,11 @@ fn load_all_mpts_ext_to_leaf() -> Result<()> { test_account_1().code_hash.into_uint(), // Values used for hashing. type_extension, - 3.into(), // 3 nibbles + 64.into(), // should be 3 nibbles but keys are extended for `Type1World` 0xABC.into(), // key part 9.into(), // Pointer to the leaf node immediately below. type_leaf, - 3.into(), // 3 nibbles + 64.into(), // should be 3 nibbles but keys are extended for `Type1World` 0xDEF.into(), // key part 13.into(), // value pointer test_account_1().nonce, From 942b8db9bcb086e71cacb30937f47bf5ac162248 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 5 Nov 2024 16:43:10 -0500 Subject: [PATCH 47/60] Refactor --- .../benches/fibonacci_25m_gas.rs | 30 +-- evm_arithmetization/src/all_stark.rs | 2 +- evm_arithmetization/src/cpu/jumps.rs | 4 +- .../src/cpu/kernel/aggregator.rs | 18 +- .../src/cpu/kernel/interpreter.rs | 4 +- .../src/cpu/kernel/tests/account_code.rs | 25 +- .../src/cpu/kernel/tests/add11.rs | 10 +- .../src/cpu/kernel/tests/mod.rs | 34 --- .../src/cpu/kernel/tests/mpt/delete.rs | 7 +- .../src/cpu/kernel/tests/mpt/hash.rs | 15 +- .../src/cpu/kernel/tests/mpt/linked_list.rs | 10 +- .../src/cpu/kernel/tests/mpt/load.rs | 10 +- .../src/cpu/kernel/tests/mpt/mod.rs | 41 +-- .../src/cpu/kernel/tests/mpt/read.rs | 7 +- .../src/generation/linked_list.rs | 4 +- evm_arithmetization/src/generation/mod.rs | 4 +- evm_arithmetization/src/generation/mpt.rs | 6 +- .../src/generation/prover_input.rs | 14 +- evm_arithmetization/src/generation/state.rs | 7 +- .../src/generation/trie_extractor.rs | 4 +- evm_arithmetization/src/testing_utils.rs | 37 ++- evm_arithmetization/tests/add11_yml.rs | 23 +- evm_arithmetization/tests/erc20.rs | 25 +- evm_arithmetization/tests/erc721.rs | 25 +- evm_arithmetization/tests/global_exit_root.rs | 241 ++++++++---------- evm_arithmetization/tests/log_opcode.rs | 25 +- evm_arithmetization/tests/selfdestruct.rs | 24 +- evm_arithmetization/tests/simple_transfer.rs | 25 +- evm_arithmetization/tests/two_to_one_block.rs | 26 +- evm_arithmetization/tests/withdrawals.rs | 25 +- 30 files changed, 241 insertions(+), 491 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 32eefdffe..e2eea3ada 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -22,6 +22,7 @@ use evm_arithmetization::generation::mpt::{ use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::simulate_execution; +use evm_arithmetization::testing_utils::get_state_world; #[cfg(feature = "eth_mainnet")] use evm_arithmetization::testing_utils::{ beacon_roots_account_nibbles, beacon_roots_contract_from_storage, @@ -150,8 +151,7 @@ fn prepare_setup() -> anyhow::Result> { storage_tries.push((sender_state_key, Node::Empty.into())); storage_tries.push((to_state_key, Node::Empty.into())); - state_trie_before = - get_state_world_from_trie_and_storage(state_trie_before_hashed, storage_tries); + state_trie_before = get_state_world(state_trie_before_hashed, storage_tries); } #[cfg(feature = "cdk_erigon")] @@ -259,8 +259,7 @@ fn prepare_setup() -> anyhow::Result> { beacon_roots_account_nibbles(), rlp::encode(&beacon_roots_account).to_vec(), )?; - expected_state_trie_after = - get_state_world_from_trie_and_storage(expected_state_trie_after_hashed, vec![]); + expected_state_trie_after = get_state_world(expected_state_trie_after_hashed, vec![]); } #[cfg(feature = "cdk_erigon")] @@ -374,26 +373,3 @@ fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, c ); } } -#[cfg(feature = "eth_mainnet")] -use std::collections::BTreeMap; - -#[cfg(feature = "eth_mainnet")] -use evm_arithmetization::world::{tries::StateMpt, world::Type1World}; -#[cfg(feature = "eth_mainnet")] -fn get_state_world_from_trie_and_storage( - state_trie: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - use evm_arithmetization::world::tries::StorageTrie; - - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/src/all_stark.rs b/evm_arithmetization/src/all_stark.rs index d2ddedb9c..41f4010fe 100644 --- a/evm_arithmetization/src/all_stark.rs +++ b/evm_arithmetization/src/all_stark.rs @@ -91,7 +91,7 @@ impl Deref for Table { fn deref(&self) -> &Self::Target { // Hacky way to implement `Deref` for `Table` so that we don't have to // call `Table::Foo as usize`, but perhaps too ugly to be worth it. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] return [&0, &1, &2, &3, &4, &5, &6, &7, &8][*self as TableIdx]; #[cfg(feature = "cdk_erigon")] diff --git a/evm_arithmetization/src/cpu/jumps.rs b/evm_arithmetization/src/cpu/jumps.rs index 0d814cc90..c100c4f91 100644 --- a/evm_arithmetization/src/cpu/jumps.rs +++ b/evm_arithmetization/src/cpu/jumps.rs @@ -122,7 +122,7 @@ pub(crate) fn eval_packed_jump_jumpi( yield_constr.constraint(filter * jumps_lv.should_jump * dst_hi_sum); // We skip jump destinations verification with `cdk_erigon`. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] { let jumpdest_flag_channel = lv.mem_channels[NUM_GP_CHANNELS - 1]; @@ -289,7 +289,7 @@ pub(crate) fn eval_ext_circuit_jump_jumpi, const D: } // We skip jump destinations verification with `cdk_erigon`. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] { let jumpdest_flag_channel = lv.mem_channels[NUM_GP_CHANNELS - 1]; diff --git a/evm_arithmetization/src/cpu/kernel/aggregator.rs b/evm_arithmetization/src/cpu/kernel/aggregator.rs index 947367d31..984f583fe 100644 --- a/evm_arithmetization/src/cpu/kernel/aggregator.rs +++ b/evm_arithmetization/src/cpu/kernel/aggregator.rs @@ -11,8 +11,10 @@ use crate::cpu::kernel::parser::parse; pub const NUMBER_KERNEL_FILES: usize = if cfg!(feature = "eth_mainnet") { 158 -} else if cfg!(feature = "cdk_erigon") || cfg!(feature = "polygon_pos") { +} else if cfg!(feature = "cdk_erigon") { 159 +} else if cfg!(feature = "polygon_pos") { + 154 } else { // unreachable 0 @@ -37,7 +39,7 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/core/call_gas.asm"), include_str!("asm/core/create.asm"), include_str!("asm/core/create_addresses.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/core/create_contract_account.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/core/create_type2_contract_account.asm"), @@ -45,13 +47,13 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/core/create_receipt.asm"), include_str!("asm/core/gas.asm"), include_str!("asm/core/intrinsic_gas.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/core/jumpdest_analysis.asm"), include_str!("asm/core/nonce.asm"), include_str!("asm/core/process_txn.asm"), include_str!("asm/core/syscall.asm"), include_str!("asm/core/terminate.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/core/transfer.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/core/transfer_cdk_erigon.asm"), @@ -127,13 +129,13 @@ pub static KERNEL_FILES: [&str; NUMBER_KERNEL_FILES] = [ include_str!("asm/hash/sha2/temp_words.asm"), include_str!("asm/hash/sha2/write_length.asm"), include_str!("asm/main.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/linked_list/accounts_linked_list.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/linked_list/storage_linked_list.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/linked_list/final_tries.asm"), - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] include_str!("asm/linked_list/initial_tries.asm"), #[cfg(feature = "cdk_erigon")] include_str!("asm/linked_list/type2/state_linked_list.asm"), diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 297664e8c..3fa7d6354 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -299,8 +299,8 @@ impl Interpreter { ), ( GlobalMetadata::StateTrieRootDigestBefore, - // TODO: We should reuse the serilized trie in memory. - #[cfg(feature = "eth_mainnet")] + // TODO: We should reuse the serialized trie in memory. + #[cfg(not(feature = "cdk_erigon"))] h2u(tries .state_trie .state diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 3c424988c..a883102e8 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -19,7 +19,7 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; use crate::generation::mpt::{load_state_mpt, AccountRlp, EitherRlp, MptAccountRlp, SmtAccountRlp}; use crate::generation::TrieInputs; @@ -41,7 +41,7 @@ pub(crate) fn initialize_mpts( } // Load all MPTs. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] { let (mut trie_root_ptrs, state_leaves, storage_leaves, trie_data) = load_linked_lists_and_txn_and_receipt_mpts( @@ -504,8 +504,10 @@ fn prepare_interpreter_all_accounts( /// Tests an SSTORE within a code similar to the contract code in add11_yml. #[test] -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] fn sstore() -> Result<()> { + use crate::testing_utils::get_state_world; + init_logger(); // We take the same `to` account as in add11_yml. let addr = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); @@ -528,7 +530,7 @@ fn sstore() -> Result<()> { let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert(addr_nibbles, account_before.rlp_encode().to_vec())?; - let state_trie = get_state_world_no_storage(state_trie_before); + let state_trie = get_state_world(state_trie_before, vec![]); let trie_inputs = TrieInputs { state_trie, @@ -600,7 +602,7 @@ fn sstore() -> Result<()> { /// Tests an SLOAD within a code similar to the contract code in add11_yml. #[test] -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] fn sload() -> Result<()> { use std::collections::BTreeMap; @@ -720,19 +722,6 @@ fn sload() -> Result<()> { Ok(()) } -#[cfg(feature = "eth_mainnet")] -pub(crate) fn get_state_world_no_storage(state_trie: HashedPartialTrie) -> StateWorld { - use std::collections::BTreeMap; - - use crate::world::{tries::StateMpt, world::Type1World}; - - StateWorld { - state: Either::Left( - Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(), - ), - } -} - fn init_logger() { let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); } diff --git a/evm_arithmetization/src/cpu/kernel/tests/add11.rs b/evm_arithmetization/src/cpu/kernel/tests/add11.rs index b2228ee5d..e0c08dc95 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/add11.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/add11.rs @@ -13,7 +13,6 @@ use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::field::types::Field; use smt_trie::code::hash_bytecode_u256; -use super::get_state_world_from_trie_and_storage; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; use crate::generation::mpt::{ @@ -21,10 +20,7 @@ use crate::generation::mpt::{ }; use crate::generation::TrieInputs; use crate::proof::{BlockHashes, BlockMetadata, TrieRoots}; -use crate::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, -}; +use crate::testing_utils::*; use crate::{GenerationInputs, EMPTY_CONSOLIDATED_BLOCKHASH}; #[test] @@ -122,7 +118,7 @@ fn test_add11_yml() { storage_tries.push((to_hashed, Node::Empty.into())); - let state_trie = get_state_world_from_trie_and_storage(state_trie_before, storage_tries); + let state_trie = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie, transactions_trie: Node::Empty.into(), @@ -385,7 +381,7 @@ fn test_add11_yml_with_exception() { storage_tries.push((to_hashed, Node::Empty.into())); - let state_trie = get_state_world_from_trie_and_storage(state_trie_before, storage_tries); + let state_trie = get_state_world(state_trie_before, storage_tries); let tries_before = TrieInputs { state_trie, diff --git a/evm_arithmetization/src/cpu/kernel/tests/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mod.rs index d81042764..4fce68600 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mod.rs @@ -30,7 +30,6 @@ use std::{ops::Range, str::FromStr}; use anyhow::Result; use ethereum_types::U256; -use mpt_trie::partial_trie::HashedPartialTrie; use plonky2::hash::hash_types::RichField; use super::{ @@ -324,36 +323,3 @@ impl Interpreter { self.generation_state.registers.context = context; } } - -#[cfg(feature = "eth_mainnet")] -use std::collections::BTreeMap; - -#[cfg(feature = "eth_mainnet")] -use keccak_hash::H256; - -#[cfg(feature = "eth_mainnet")] -use crate::world::{ - tries::StateMpt, - world::{StateWorld, Type1World}, -}; - -#[cfg(feature = "eth_mainnet")] -fn get_state_world_from_trie_and_storage( - state_trie: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - use either::Either; - - use crate::world::tries::StorageTrie; - - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs index f65171420..9c5abada6 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs @@ -10,12 +10,11 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; -use crate::cpu::kernel::tests::mpt::{ - get_state_world_no_storage, nibbles_64, test_account_1_rlp, test_account_2, -}; +use crate::cpu::kernel::tests::mpt::{nibbles_64, test_account_1_rlp, test_account_2}; use crate::generation::mpt::MptAccountRlp; use crate::generation::TrieInputs; use crate::memory::segments::Segment; +use crate::testing_utils::get_state_world; use crate::util::h2u; use crate::Node; @@ -95,7 +94,7 @@ fn test_state_trie( // Ignore any storage_root; see documentation note. account.storage_root = HashedPartialTrie::from(Node::Empty).hash(); - let state_world = get_state_world_no_storage(state_trie.clone()); + let state_world = get_state_world(state_trie.clone(), vec![]); let trie_inputs = TrieInputs { state_trie: state_world, transactions_trie: Default::default(), diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs index a4278d756..f5a16803b 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs @@ -2,13 +2,13 @@ use anyhow::Result; use ethereum_types::{BigEndianHash, H256}; use plonky2::field::goldilocks_field::GoldilocksField as F; -use super::get_state_world_no_storage; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1_rlp, test_account_2_rlp}; use crate::generation::TrieInputs; +use crate::testing_utils::get_state_world; use crate::world::world::World; use crate::Node; @@ -28,12 +28,13 @@ fn mpt_hash_empty() -> Result<()> { #[test] fn mpt_hash_empty_branch() -> Result<()> { let children = core::array::from_fn(|_| Node::Empty.into()); - let state_trie = get_state_world_no_storage( + let state_trie = get_state_world( Node::Branch { children, value: vec![], } .into(), + vec![], ); let trie_inputs = TrieInputs { state_trie, @@ -47,7 +48,7 @@ fn mpt_hash_empty_branch() -> Result<()> { fn mpt_hash_hash() -> Result<()> { let hash = H256::random(); - let state_trie = get_state_world_no_storage(Node::Hash(hash).into()); + let state_trie = get_state_world(Node::Hash(hash).into(), vec![]); let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), @@ -59,12 +60,13 @@ fn mpt_hash_hash() -> Result<()> { #[test] fn mpt_hash_leaf() -> Result<()> { - let state_trie = get_state_world_no_storage( + let state_trie = get_state_world( Node::Leaf { nibbles: 0xABC_u64.into(), value: test_account_1_rlp(), } .into(), + vec![], ); let trie_inputs = TrieInputs { state_trie, @@ -76,7 +78,7 @@ fn mpt_hash_leaf() -> Result<()> { #[test] fn mpt_hash_extension_to_leaf() -> Result<()> { - let state_trie = get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())); + let state_trie = get_state_world(extension_to_leaf(test_account_1_rlp()), vec![]); let trie_inputs = TrieInputs { state_trie, transactions_trie: Default::default(), @@ -95,12 +97,13 @@ fn mpt_hash_branch_to_leaf() -> Result<()> { let mut children = core::array::from_fn(|_| Node::Empty.into()); children[3] = leaf; - let state_trie = get_state_world_no_storage( + let state_trie = get_state_world( Node::Branch { children, value: vec![], } .into(), + vec![], ); let trie_inputs = TrieInputs { 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 8c56432a8..076e9432e 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs @@ -15,14 +15,14 @@ use crate::cpu::kernel::interpreter::Interpreter; use crate::generation::linked_list::testing::LinkedList; use crate::generation::linked_list::ACCOUNTS_LINKED_LIST_NODE_SIZE; use crate::generation::linked_list::STATE_LINKED_LIST_NODE_SIZE; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] use crate::generation::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use crate::memory::segments::Segment; use crate::witness::memory::MemoryAddress; use crate::witness::memory::MemorySegmentState; pub(crate) type AccountsLinkedList<'a> = LinkedList<'a, ACCOUNTS_LINKED_LIST_NODE_SIZE>; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) type StorageLinkedList<'a> = LinkedList<'a, STORAGE_LINKED_LIST_NODE_SIZE>; pub(crate) type StateLinkedList<'a> = LinkedList<'a, STATE_LINKED_LIST_NODE_SIZE>; @@ -112,7 +112,7 @@ fn test_list_iterator() -> Result<()> { .generation_state .memory .get_preinit_memory(Segment::StorageLinkedList); - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] { let mut storage_list = StorageLinkedList::from_mem_and_segment(&accounts_mem, Segment::StorageLinkedList) @@ -221,7 +221,7 @@ fn test_insert_account() -> Result<()> { } #[test] -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] fn test_insert_storage() -> Result<()> { init_logger(); @@ -497,7 +497,7 @@ fn test_insert_and_delete_accounts() -> Result<()> { } #[test] -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] fn test_insert_and_delete_storage() -> Result<()> { init_logger(); diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs index 2abbcfac9..be0b3f2a2 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs @@ -13,10 +13,9 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::constants::trie_type::PartialTrieType; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; -use crate::cpu::kernel::tests::mpt::{ - extension_to_leaf, get_state_world_no_storage, test_account_1, test_account_1_rlp, -}; +use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1, test_account_1_rlp}; use crate::generation::TrieInputs; +use crate::testing_utils::get_state_world; use crate::world::tries::StateMpt; use crate::world::world::{StateWorld, Type1World}; use crate::Node; @@ -55,12 +54,13 @@ fn load_all_mpts_empty() -> Result<()> { #[test] fn load_all_mpts_leaf() -> Result<()> { - let state_trie = get_state_world_no_storage( + let state_trie = get_state_world( Node::Leaf { nibbles: 0xABC_u64.into(), value: test_account_1_rlp(), } .into(), + vec![], ); let trie_inputs = TrieInputs { state_trie, @@ -223,7 +223,7 @@ fn load_all_mpts_empty_branch() -> Result<()> { #[test] fn load_all_mpts_ext_to_leaf() -> Result<()> { let trie_inputs = TrieInputs { - state_trie: get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())), + state_trie: get_state_world(extension_to_leaf(test_account_1_rlp()), vec![]), transactions_trie: Default::default(), receipts_trie: Default::default(), }; diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index e9b11478e..cbe19a8b4 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeMap; - use either::Either; use ethereum_types::{BigEndianHash, H256, U256}; use mpt_trie::nibbles::Nibbles; @@ -9,22 +7,19 @@ use mpt_trie::partial_trie::PartialTrie; use crate::generation::mpt::EitherRlp; use crate::generation::mpt::MptAccountRlp; use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; -use crate::world::tries::StateMpt; -use crate::world::world::StateWorld; -use crate::world::world::Type1World; use crate::Node; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] mod delete; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] mod hash; mod hex_prefix; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] mod insert; pub(crate) mod linked_list; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] mod load; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] mod read; pub(crate) fn nibbles_64>(v: T) -> Nibbles { @@ -65,7 +60,7 @@ pub(crate) fn test_account_1_empty_storage() -> EitherRlp { } } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn test_account_1() -> MptAccountRlp { MptAccountRlp { nonce: U256::from(1111), @@ -75,7 +70,7 @@ pub(crate) fn test_account_1() -> MptAccountRlp { } } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn test_account_1_rlp() -> Vec { test_account_1().rlp_encode().to_vec() } @@ -84,7 +79,7 @@ pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { test_account_1_empty_storage().rlp_encode().to_vec() } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn test_account_2() -> MptAccountRlp { MptAccountRlp { nonce: U256::from(5555), @@ -94,7 +89,7 @@ pub(crate) fn test_account_2() -> MptAccountRlp { } } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn test_account_2_rlp() -> Vec { test_account_2().rlp_encode().to_vec() } @@ -115,21 +110,3 @@ pub(crate) fn extension_to_leaf(value: Vec) -> HashedPartialTrie { } .into() } - -#[cfg(feature = "eth_mainnet")] -pub(crate) fn get_state_world_no_storage(state_trie: HashedPartialTrie) -> StateWorld { - // `Type1World` expects full keys, so we manually expand the nibbles here. - - use mpt_trie::utils::TryFromIterator as _; - let state_trie = HashedPartialTrie::try_from_iter(state_trie.items().map(|(mut key, val)| { - key.count = 64; - (key, val) - })) - .expect("This should never fail"); - - StateWorld { - state: Either::Left( - Type1World::new(StateMpt::new_with_inner(state_trie), BTreeMap::default()).unwrap(), - ), - } -} diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs index 9d32e3195..6e617f0a7 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs @@ -6,15 +6,14 @@ use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; -use crate::cpu::kernel::tests::mpt::{ - extension_to_leaf, get_state_world_no_storage, test_account_1, test_account_1_rlp, -}; +use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1, test_account_1_rlp}; use crate::generation::TrieInputs; +use crate::testing_utils::get_state_world; #[test] fn mpt_read() -> Result<()> { let trie_inputs = TrieInputs { - state_trie: get_state_world_no_storage(extension_to_leaf(test_account_1_rlp())), + state_trie: get_state_world(extension_to_leaf(test_account_1_rlp()), vec![]), transactions_trie: Default::default(), receipts_trie: Default::default(), }; diff --git a/evm_arithmetization/src/generation/linked_list.rs b/evm_arithmetization/src/generation/linked_list.rs index 426c809a4..a6e7d08d3 100644 --- a/evm_arithmetization/src/generation/linked_list.rs +++ b/evm_arithmetization/src/generation/linked_list.rs @@ -4,7 +4,7 @@ use ethereum_types::U256; use serde::{Deserialize, Serialize}; pub const ACCOUNTS_LINKED_LIST_NODE_SIZE: usize = 4; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub const STORAGE_LINKED_LIST_NODE_SIZE: usize = 5; pub const STATE_LINKED_LIST_NODE_SIZE: usize = 4; @@ -27,7 +27,7 @@ pub(crate) struct AccessLinkedListsPtrs { // Provides quick access to pointers that reference the memory location // of state nodes. #[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) struct StateLinkedListsPtrs { /// Each entry contains the pair (key, ptr) where key is the (hashed) key /// of an account in the accounts linked list, and ptr is the respective diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index 39a89d4e4..f924fa4fa 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -27,7 +27,7 @@ use crate::cpu::columns::CpuColumnsView; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::generation::state::{GenerationState, State}; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] use crate::generation::trie_extractor::get_state_trie; use crate::generation::trie_extractor::{get_receipt_trie, get_txn_trie}; use crate::memory::segments::{Segment, PREINITIALIZED_SEGMENTS_INDICES}; @@ -702,7 +702,7 @@ pub(crate) fn collect_debug_tries( .inspect_err(|e| error!("failed to retrieve state trie pointer: {e:?}")) .ok()?; - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] let state_trie = get_state_trie::(&state.memory, state_trie_ptr) .inspect_err(|e| error!("unable to retrieve state trie for debugging purposes: {e:?}")) .ok()?; diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index d3a4ef27f..682419347 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -12,7 +12,7 @@ use rlp::{Decodable, DecoderError, Encodable, PayloadInfo, Rlp, RlpStream}; use rlp_derive::{RlpDecodable, RlpEncodable}; use serde::{Deserialize, Serialize}; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] use super::linked_list::{ empty_list_mem, ACCOUNTS_LINKED_LIST_NODE_SIZE, STORAGE_LINKED_LIST_NODE_SIZE, }; @@ -518,7 +518,7 @@ fn load_state_trie( } } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] fn get_state_and_storage_leaves( trie: &HashedPartialTrie, key: Nibbles, @@ -728,7 +728,7 @@ type LinkedListsAndTrieData = ( Vec>, ); -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( accounts_pointers: &mut BTreeMap, storage_pointers: &mut BTreeMap<(U256, U256), usize>, diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index b54b9d40c..ae221b580 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; #[cfg(test)] use super::linked_list::testing::{LinkedList, ADDRESSES_ACCESS_LIST_LEN}; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] use super::linked_list::STORAGE_LINKED_LIST_NODE_SIZE; use super::linked_list::{AccessLinkedListsPtrs, ACCOUNTS_LINKED_LIST_NODE_SIZE, DUMMYHEAD}; use super::mpt::load_state_mpt; @@ -374,7 +374,7 @@ impl GenerationState { /// Generates either the next used jump address or the proof for the last /// jump address. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn run_linked_list(&mut self, input_fn: &ProverInputFn) -> Result { match input_fn.0[1].as_str() { "insert_account" | "search_account" => self.run_next_insert_account(input_fn), @@ -574,7 +574,7 @@ impl GenerationState { /// Returns a pointer to a node in the list such that /// `node[0] <= addr < next_node[0]` and `addr` is the top of the stack. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn run_next_insert_account(&mut self, input_fn: &ProverInputFn) -> Result { let addr = stack_peek(self, 0)?; let (&pred_addr, &pred_ptr) = self @@ -624,7 +624,7 @@ impl GenerationState { /// `node[0] <= addr < next_node[0]`, or node[0] == addr and `node[1] <= /// key < next_node[1]`, where `addr` and `key` are the elements at the top /// of the stack. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn run_next_insert_slot(&mut self, input_fn: &ProverInputFn) -> Result { let addr = stack_peek(self, 0)?; let key = stack_peek(self, 1)?; @@ -652,7 +652,7 @@ impl GenerationState { /// Returns a pointer `ptr` to a node of the form [..] -> [next_addr, ..] /// such that `next_addr = addr` and `addr` is the top of the stack. /// If the element is not in the list, returns an error. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn run_next_remove_account(&mut self) -> Result { let addr = stack_peek(self, 0)?; @@ -697,7 +697,7 @@ impl GenerationState { /// such that `next_addr == addr` and `next_key == key`, /// and `addr, key` are the elements at the top of the stack. /// If the element is not in the list, loops forever. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn run_next_remove_slot(&mut self) -> Result { let addr = stack_peek(self, 0)?; let key = stack_peek(self, 1)?; @@ -722,7 +722,7 @@ impl GenerationState { /// `next_addr = @U256_MAX`. This is used to determine the first storage /// node for the account at `addr`. `addr` is the element at the top of the /// stack. - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn run_next_remove_address_slots(&mut self) -> Result { let addr = stack_peek(self, 0)?; diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 56778fdf2..bb8a02d33 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -20,7 +20,7 @@ use crate::cpu::stack::MAX_USER_STACK_SIZE; #[cfg(feature = "cdk_erigon")] use crate::generation::linked_list::{empty_list_mem, STATE_LINKED_LIST_NODE_SIZE}; use crate::generation::linked_list::{AccessLinkedListsPtrs, StateLinkedListsPtrs}; -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; use crate::generation::mpt::{load_receipts_mpt, load_transactions_mpt}; use crate::generation::rlp::all_rlp_prover_inputs_reversed; @@ -436,7 +436,7 @@ impl GenerationState { } } - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] fn preinitialize_linked_lists(&mut self, trie_inputs: &TrieInputs) { let generation_state = self.get_mut_generation_state(); let (_trie_root_ptrs, state_leaves, storage_leaves, trie_data) = @@ -446,7 +446,6 @@ impl GenerationState { trie_inputs, ) .expect("Invalid MPT data for preinitialization"); - // TODO: REMOVE self.memory.insert_preinitialized_segment( Segment::AccountsLinkedList, crate::witness::memory::MemorySegmentState { @@ -505,7 +504,7 @@ impl GenerationState { let bignum_modmul_result_limbs = Vec::new(); log::debug!("smt trie = {:?}", inputs.tries.state_trie); - #[cfg(feature = "eth_mainnet")] + #[cfg(not(feature = "cdk_erigon"))] { let mut state = Self { inputs: inputs.trim(), diff --git a/evm_arithmetization/src/generation/trie_extractor.rs b/evm_arithmetization/src/generation/trie_extractor.rs index c13d56625..342167543 100644 --- a/evm_arithmetization/src/generation/trie_extractor.rs +++ b/evm_arithmetization/src/generation/trie_extractor.rs @@ -89,7 +89,7 @@ pub(crate) fn read_logs( .collect() } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn read_state_rlp_value( memory: &MemoryState, slice: &MemoryValues, @@ -133,7 +133,7 @@ pub(crate) fn read_receipt_rlp_value( Ok(bytes) } -#[cfg(feature = "eth_mainnet")] +#[cfg(not(feature = "cdk_erigon"))] pub(crate) fn get_state_trie( memory: &MemoryState, ptr: usize, diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index 4033fdfa7..06f1bb82f 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -206,7 +206,7 @@ pub fn update_scalable_account_storage( insert_storage(storage_trie, slot.into_uint(), h2u(initial_trie_hash)) } -#[cfg(feature = "eth_mainnet")] +#[cfg(feature = "cdk_erigon")] pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { MptAccountRlp { storage_root: storage_trie.hash(), @@ -214,7 +214,7 @@ pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccount } } -#[cfg(feature = "eth_mainnet")] +#[cfg(feature = "cdk_erigon")] pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { MptAccountRlp { storage_root: storage_trie.hash(), @@ -283,6 +283,39 @@ pub fn segment_with_empty_tables() -> Result<( Ok((trimmed_inputs, segment_data)) } +#[cfg(not(feature = "cdk_erigon"))] +pub fn get_state_world( + state: HashedPartialTrie, + storage_tries: Vec<(H256, HashedPartialTrie)>, +) -> StateWorld { + use std::collections::BTreeMap; + + use either::Either; + // `Type1World` expects full keys, so we manually expand the nibbles here. + use mpt_trie::utils::TryFromIterator as _; + + use crate::world::{ + tries::{StateMpt, StorageTrie}, + world::Type1World, + }; + let state = HashedPartialTrie::try_from_iter(state.items().map(|(mut key, val)| { + key.count = 64; + (key, val) + })) + .expect("This should never fail"); + + let mut type1world = + Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); + let mut init_storage = BTreeMap::default(); + for (storage, v) in storage_tries { + init_storage.insert(storage, StorageTrie::new_with_trie(v)); + } + type1world.set_storage(init_storage); + StateWorld { + state: Either::Left(type1world), + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index a397466b2..9024b2edd 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -1,6 +1,6 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use std::str::FromStr; use std::time::Duration; @@ -13,12 +13,11 @@ use evm_arithmetization::generation::TrieInputs; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, + beacon_roots_account_nibbles, beacon_roots_contract_from_storage, get_state_world, init_logger, preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, TEST_STARK_CONFIG, }; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World, World}; +use evm_arithmetization::world::world::World; use evm_arithmetization::{AllStark, GenerationInputs, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -275,19 +274,3 @@ fn add11_yml() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index 447fab095..d6df2f9a0 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -1,6 +1,5 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::BTreeMap; use std::str::FromStr; use std::time::Duration; @@ -10,14 +9,8 @@ use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountR use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, create_account_storage, - init_logger, preinitialized_state_and_storage_tries, sd2u, update_beacon_roots_account_storage, - TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -297,19 +290,3 @@ fn bloom() -> [U256; 8] { .collect::>(); bloom.try_into().unwrap() } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index 8377a11f9..fffc1cd15 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -1,6 +1,5 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::BTreeMap; use std::str::FromStr; use std::time::Duration; @@ -10,14 +9,8 @@ use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountR use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, create_account_storage, - init_logger, preinitialized_state_and_storage_tries, sd2u, sh2u, - update_beacon_roots_account_storage, TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -319,19 +312,3 @@ fn add_to_bloom(bloom: &mut [u8; 256], bloom_entry: &[u8]) { bloom[byte_index as usize] |= bit_value; } } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/global_exit_root.rs b/evm_arithmetization/tests/global_exit_root.rs index 10d1ecbcf..6abbcacdf 100644 --- a/evm_arithmetization/tests/global_exit_root.rs +++ b/evm_arithmetization/tests/global_exit_root.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "eth_mainnet")] +#![cfg(feature = "cdk_erigon")] use std::collections::{BTreeMap, HashMap}; use std::time::Duration; @@ -8,12 +8,7 @@ use ethereum_types::H256; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - ger_account_nibbles, ger_contract_from_storage, init_logger, scalable_account_nibbles, - scalable_contract_from_storage, update_ger_account_storage, update_scalable_account_storage, - ADDRESS_SCALABLE_L2_ADDRESS_HASHED, GLOBAL_EXIT_ROOT_ACCOUNT, GLOBAL_EXIT_ROOT_ADDRESS_HASHED, - TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; use evm_arithmetization::world::world::{StateWorld, Type1World}; @@ -29,125 +24,113 @@ type F = GoldilocksField; const D: usize = 2; type C = PoseidonGoldilocksConfig; -/// Test pre-state execution as performed by cdk-erigon. -#[test] -fn test_global_exit_root() -> anyhow::Result<()> { - init_logger(); - - let all_stark = AllStark::::default(); - let config = TEST_STARK_CONFIG; - - let block_metadata = BlockMetadata { - block_timestamp: 1.into(), - block_number: 42.into(), - ..BlockMetadata::default() - }; - - let mut state_trie_before = HashedPartialTrie::from(Node::Empty); - let mut storage_tries = vec![]; - state_trie_before.insert( - ger_account_nibbles(), - rlp::encode(&GLOBAL_EXIT_ROOT_ACCOUNT).to_vec(), - )?; - - let mut ger_account_storage = HashedPartialTrie::from(Node::Empty); - let mut scalable_account_storage = HashedPartialTrie::from(Node::Empty); - - storage_tries.push((GLOBAL_EXIT_ROOT_ADDRESS_HASHED, ger_account_storage.clone())); - storage_tries.push(( - ADDRESS_SCALABLE_L2_ADDRESS_HASHED, - scalable_account_storage.clone(), - )); - - let transactions_trie = HashedPartialTrie::from(Node::Empty); - let receipts_trie = HashedPartialTrie::from(Node::Empty); - - let mut contract_code = HashMap::new(); - contract_code.insert(Either::Left(keccak(vec![])), vec![]); - - let ger_data = Some((H256::random(), H256::random())); - - let state_trie_after = { - let mut trie = HashedPartialTrie::from(Node::Empty); - update_ger_account_storage(&mut ger_account_storage, ger_data)?; - update_scalable_account_storage( - &mut scalable_account_storage, - &block_metadata, - state_trie_before.hash(), - )?; - - let ger_account = ger_contract_from_storage(&ger_account_storage); - let scalable_account = scalable_contract_from_storage(&scalable_account_storage); - - trie.insert(ger_account_nibbles(), rlp::encode(&ger_account).to_vec())?; - trie.insert( - scalable_account_nibbles(), - rlp::encode(&scalable_account).to_vec(), - )?; - - trie - }; - - let trie_roots_after = TrieRoots { - state_root: state_trie_after.hash(), - transactions_root: transactions_trie.hash(), - receipts_root: receipts_trie.hash(), - }; - - let state_trie_before = get_state_world(state_trie_before, storage_tries); - let inputs = GenerationInputs:: { - signed_txns: vec![], - burn_addr: None, - withdrawals: vec![], - ger_data, - tries: TrieInputs { - state_trie: state_trie_before, - transactions_trie, - receipts_trie, - // storage_tries, - }, - trie_roots_after, - contract_code, - checkpoint_state_trie_root: HashedPartialTrie::from(Node::Empty).hash(), - checkpoint_consolidated_hash: EMPTY_CONSOLIDATED_BLOCKHASH.map(F::from_canonical_u64), - block_metadata, - txn_number_before: 0.into(), - gas_used_before: 0.into(), - gas_used_after: 0.into(), - block_hashes: BlockHashes { - prev_hashes: vec![H256::default(); 256], - cur_hash: H256::default(), - }, - }; - - let max_cpu_len_log = 20; - - let mut timing = TimingTree::new("prove", log::Level::Debug); - let proofs = prove_all_segments::( - &all_stark, - &config, - inputs, - max_cpu_len_log, - &mut timing, - None, - )?; - timing.filter(Duration::from_millis(100)).print(); - - verify_all_proofs(&all_stark, &proofs, &config) -} - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} +// /// Test pre-state execution as performed by cdk-erigon. +// TODO: fix this with SMT +// #[test] +// fn test_global_exit_root() -> anyhow::Result<()> { +// init_logger(); + +// let all_stark = AllStark::::default(); +// let config = TEST_STARK_CONFIG; + +// let block_metadata = BlockMetadata { +// block_timestamp: 1.into(), +// block_number: 42.into(), +// ..BlockMetadata::default() +// }; + +// let mut state_trie_before = HashedPartialTrie::from(Node::Empty); +// let mut storage_tries = vec![]; +// state_trie_before.insert( +// ger_account_nibbles(), +// rlp::encode(&GLOBAL_EXIT_ROOT_ACCOUNT).to_vec(), +// )?; + +// let mut ger_account_storage = HashedPartialTrie::from(Node::Empty); +// let mut scalable_account_storage = HashedPartialTrie::from(Node::Empty); + +// storage_tries.push((GLOBAL_EXIT_ROOT_ADDRESS_HASHED, +// ger_account_storage.clone())); storage_tries.push(( +// ADDRESS_SCALABLE_L2_ADDRESS_HASHED, +// scalable_account_storage.clone(), +// )); + +// let transactions_trie = HashedPartialTrie::from(Node::Empty); +// let receipts_trie = HashedPartialTrie::from(Node::Empty); + +// let mut contract_code = HashMap::new(); +// contract_code.insert(Either::Left(keccak(vec![])), vec![]); + +// let ger_data = Some((H256::random(), H256::random())); + +// let state_trie_after = { +// let mut trie = HashedPartialTrie::from(Node::Empty); +// update_ger_account_storage(&mut ger_account_storage, ger_data)?; +// update_scalable_account_storage( +// &mut scalable_account_storage, +// &block_metadata, +// state_trie_before.hash(), +// )?; + +// let ger_account = ger_contract_from_storage(&ger_account_storage); +// let scalable_account = +// scalable_contract_from_storage(&scalable_account_storage); + +// trie.insert(ger_account_nibbles(), +// rlp::encode(&ger_account).to_vec())?; trie.insert( +// scalable_account_nibbles(), +// rlp::encode(&scalable_account).to_vec(), +// )?; + +// trie +// }; + +// let trie_roots_after = TrieRoots { +// state_root: state_trie_after.hash(), +// transactions_root: transactions_trie.hash(), +// receipts_root: receipts_trie.hash(), +// }; + +// let state_trie_before = get_state_world(state_trie_before, +// storage_tries); let inputs = GenerationInputs:: { +// signed_txns: vec![], +// burn_addr: None, +// withdrawals: vec![], +// ger_data, +// tries: TrieInputs { +// state_trie: state_trie_before, +// transactions_trie, +// receipts_trie, +// // storage_tries, +// }, +// trie_roots_after, +// contract_code, +// checkpoint_state_trie_root: +// HashedPartialTrie::from(Node::Empty).hash(), +// checkpoint_consolidated_hash: +// EMPTY_CONSOLIDATED_BLOCKHASH.map(F::from_canonical_u64), +// block_metadata, +// txn_number_before: 0.into(), +// gas_used_before: 0.into(), +// gas_used_after: 0.into(), +// block_hashes: BlockHashes { +// prev_hashes: vec![H256::default(); 256], +// cur_hash: H256::default(), +// }, +// }; + +// let max_cpu_len_log = 20; + +// let mut timing = TimingTree::new("prove", log::Level::Debug); +// let proofs = prove_all_segments::( +// &all_stark, +// &config, +// inputs, +// max_cpu_len_log, +// &mut timing, +// None, +// )?; +// timing.filter(Duration::from_millis(100)).print(); + +// verify_all_proofs(&all_stark, &proofs, &config) +// } diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 5f9152a3d..41c5a4a8d 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -1,6 +1,6 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use std::str::FromStr; use std::time::Duration; @@ -14,13 +14,8 @@ use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountR use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -403,19 +398,3 @@ fn test_txn_and_receipt_trie_hash() -> anyhow::Result<()> { Ok(()) } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index e9f24becc..8435aca90 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -1,6 +1,5 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::BTreeMap; use std::str::FromStr; use std::time::Duration; @@ -10,13 +9,8 @@ use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -197,19 +191,3 @@ fn test_selfdestruct() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index 482b0f006..8d28bd3a1 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -1,6 +1,6 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use std::str::FromStr; use std::time::Duration; @@ -10,13 +10,8 @@ use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -184,19 +179,3 @@ fn test_simple_transfer() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/two_to_one_block.rs b/evm_arithmetization/tests/two_to_one_block.rs index 021b27e29..75c97cece 100644 --- a/evm_arithmetization/tests/two_to_one_block.rs +++ b/evm_arithmetization/tests/two_to_one_block.rs @@ -1,8 +1,5 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::BTreeMap; - -use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::fixed_recursive_verifier::{ extract_block_final_public_values, extract_two_to_one_block_hash, RecursionConfig, @@ -11,12 +8,7 @@ use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{ BlockMetadata, FinalPublicValues, PublicValues, TrieRoots, EMPTY_CONSOLIDATED_BLOCKHASH, }; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, TEST_STARK_CONFIG, -}; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::{AllRecursiveCircuits, AllStark, Node, StarkConfig}; use hex_literal::hex; use mpt_trie::partial_trie::{HashedPartialTrie, PartialTrie}; @@ -286,19 +278,3 @@ fn test_two_to_one_block_aggregation() -> anyhow::Result<()> { Ok(()) } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index 72871dce1..cad90fe6c 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -1,6 +1,6 @@ #![cfg(feature = "eth_mainnet")] -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap; use std::time::Duration; use either::Either; @@ -9,13 +9,8 @@ use evm_arithmetization::generation::mpt::MptAccountRlp; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; -use evm_arithmetization::testing_utils::{ - beacon_roots_account_nibbles, beacon_roots_contract_from_storage, init_logger, - preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, TEST_STARK_CONFIG, -}; +use evm_arithmetization::testing_utils::*; use evm_arithmetization::verifier::testing::verify_all_proofs; -use evm_arithmetization::world::tries::{StateMpt, StorageTrie}; -use evm_arithmetization::world::world::{StateWorld, Type1World}; use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use keccak_hash::keccak; use mpt_trie::nibbles::Nibbles; @@ -127,19 +122,3 @@ fn test_withdrawals() -> anyhow::Result<()> { verify_all_proofs(&all_stark, &proofs, &config) } - -fn get_state_world( - state: HashedPartialTrie, - storage_tries: Vec<(H256, HashedPartialTrie)>, -) -> StateWorld { - let mut type1world = - Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); - let mut init_storage = BTreeMap::default(); - for (storage, v) in storage_tries { - init_storage.insert(storage, StorageTrie::new_with_trie(v)); - } - type1world.set_storage(init_storage); - StateWorld { - state: Either::Left(type1world), - } -} From ff886b4dfd52abe0da8b91f25bdaa9c0594f0499 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Tue, 5 Nov 2024 13:35:02 +0100 Subject: [PATCH 48/60] Fix erc20 --- .../src/cpu/kernel/asm/account_code.asm | 2 +- .../src/cpu/kernel/asm/beacon_roots.asm | 17 +++--- .../src/cpu/kernel/asm/main.asm | 23 ++++++-- .../src/generation/prover_input.rs | 23 ++++---- evm_arithmetization/src/witness/transition.rs | 53 +++++++++++++++++-- evm_arithmetization/tests/erc20.rs | 1 + 6 files changed, 96 insertions(+), 23 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 550b85ae6..17a9be1b1 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -121,7 +121,7 @@ load_code_ctd: DUP1 ISZERO %jumpi(load_code_non_existent_account) // Load the code non-deterministically in memory and return the length. PROVER_INPUT(account_code) -#[cfg(feature = eth_mainnet)] +#[cfg(not(feature = cdk_erigon))] { %stack (code_size, codehash, ctx, retdest) -> (ctx, code_size, codehash, retdest, code_size) // Check that the hash of the loaded code equals `codehash`. diff --git a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm index ef07cfe28..a550b1cbd 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm @@ -15,18 +15,23 @@ global set_beacon_root: // stack: timestamp, 8191, timestamp, retdest MOD // stack: timestamp_idx, timestamp, retdest + %slot_to_storage_key + // stack: timestamp_slot_key, timestamp, retdest PUSH @BEACON_ROOTS_CONTRACT_STATE_KEY %parent_beacon_block_root - // stack: calldata, state_key, timestamp_idx, timestamp, retdest + // stack: calldata, state_key, timestamp_slot_key, timestamp, retdest PUSH @HISTORY_BUFFER_LENGTH - DUP4 - // stack: timestamp_idx, calldata, state_key, timestamp_idx, timestamp, retdest + DUP5 + MOD + // stack: timestamp_idx, calldata, state_key, timestamp_slot_key, timestamp, retdest %add_const(@HISTORY_BUFFER_LENGTH) - // stack: root_idx, calldata, state_key, timestamp_idx, timestamp, retdest + // stack: root_idx, calldata, state_key, timestamp_slot_key, timestamp, retdest + %slot_to_storage_key + // stack: root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest DUP3 - // stack: state_key, root_slot_idx, calldata, state_key, timestamp_idx, timestamp, retdest + // stack: state_key, root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest DUP3 ISZERO %jumpi(delete_root_idx_slot) - // stack: state_key, root_slot_idx, calldata, state_key, timestamp_idx, timestamp, retdest + // stack: state_key, root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest %insert_slot_from_addr_key // stack: state_key, timestamp_idx, timestamp, retdest %insert_slot_from_addr_key diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 621b595b7..dc0c145f4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -96,10 +96,27 @@ global after_store_initial: global hash_initial_tries: // We compute the length of the trie data segment in `mpt_hash` so that we // can check the value provided by the prover. - // The trie data segment contains only the empty node - // The initial payloads are written twice, and each payload requires 4 elements. - PUSH 2 + #[cfg(not(feature = cdk_erigon))] + { + // First, we compute the initial size of the trie data segment. + PUSH @ACCOUNTS_LINKED_LISTS_NODE_SIZE + PUSH @SEGMENT_ACCOUNTS_LINKED_LIST + %mload_global_metadata(@GLOBAL_METADATA_ACCOUNTS_LINKED_LIST_NEXT_AVAILABLE) + SUB + // stack: accounts_ll_full_len, accounts_ll_node_size + DIV + %decrement + // stack: actual_nb_accounts + // The initial payloads are written twice, and each payload requires 4 elements. + PUSH 8 MUL + %increment + } + #[cfg(feature = cdk_erigon)] + { + // The trie data segment contains only the empty node + PUSH 2 + } // stack: init_trie_data_len PUSH @INITIAL_RLP_ADDR // stack: rlp_start, init_trie_data_len diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index b54b9d40c..f7a1d95b0 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -251,23 +251,26 @@ impl GenerationState { .contract_code .get(&codehash) .ok_or(ProgramError::ProverInputError(CodeHashNotFound))?; - let code_len = code.len(); + let mut code_len = code.len(); for &byte in code { self.memory.set(address, byte.into()); address.increment(); } - // Padding - self.memory.set(address, 1.into()); - let mut len = code_len + 1; - len = 56 * ((len + 55) / 56); - let last_byte_addr = MemoryAddress::new(context, Segment::Code, len - 1); - let mut last_byte = u256_to_usize(self.memory.get_with_init(last_byte_addr))?; - last_byte |= 0x80; - self.memory.set(last_byte_addr, last_byte.into()); + #[cfg(feature = "cdk_erigon")] + { + // Padding + self.memory.set(address, 1.into()); + code_len = code_len + 1; + code_len = 56 * ((code_len + 55) / 56); + let last_byte_addr = MemoryAddress::new(context, Segment::Code, code_len - 1); + let mut last_byte = u256_to_usize(self.memory.get_with_init(last_byte_addr))?; + last_byte |= 0x80; + self.memory.set(last_byte_addr, last_byte.into()); + } - Ok(len.into()) + Ok(code_len.into()) } // Bignum modular multiplication. diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index d47f56ab7..2a37c4517 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -1,5 +1,6 @@ use ethereum_types::U256; use log::log_enabled; +use mpt_trie::partial_trie::HashedPartialTrie; use plonky2::field::types::Field; use plonky2::hash::hash_types::RichField; @@ -12,11 +13,14 @@ use crate::cpu::kernel::constants::MAX_CODE_SIZE; use crate::cpu::kernel::opcodes::get_opcode; #[cfg(test)] use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; +#[cfg(test)] +use crate::cpu::kernel::tests::mpt::linked_list::{AccountsLinkedList, StorageLinkedList}; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::stack::{ EQ_STACK_BEHAVIOR, IS_ZERO_STACK_BEHAVIOR, JUMPI_OP, JUMP_OP, MIGHT_OVERFLOW, STACK_BEHAVIORS, }; use crate::generation::state::State; +use crate::generation::trie_extractor::get_state_trie; use crate::memory::segments::Segment; // TO REMOVE! use crate::util::u256_to_usize; @@ -289,9 +293,9 @@ pub(crate) const fn might_overflow_op(op: Operation) -> bool { pub(crate) fn log_kernel_instruction>(state: &mut S, op: Operation) { // The logic below is a bit costly, so skip it if debug logs aren't enabled. - if !log_enabled!(log::Level::Debug) { - return; - } + // if !log_enabled!(log::Level::Debug) { + // return; + // } let pc = state.get_registers().program_counter; let is_interesting_offset = KERNEL @@ -315,6 +319,49 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ), ); + if cfg!(test) { + println!("a"); + } else { + println!("b"); + } + + #[cfg(test)] + if {println!("mmmm"); KERNEL.offset_name(pc) == "mpt_hash_state_trie"} { + let mem = state + .get_generation_state() + .memory + .get_preinit_memory(Segment::AccountsLinkedList); + log::debug!( + "accounts linked list = {:?}", + AccountsLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) + ); + + let mem = state + .get_generation_state() + .memory + .get_preinit_memory(Segment::StorageLinkedList); + log::debug!( + "state linked list = {:?}", + StorageLinkedList::from_mem_and_segment(&mem, Segment::StorageLinkedList) + ); + + let state_trie_ptr = u256_to_usize( + state + .get_generation_state() + .memory + .read_global_metadata(GlobalMetadata::StateTrieRoot), + ) + .unwrap(); + + let state_trie = get_state_trie::( + &state.get_generation_state().memory, + state_trie_ptr, + ) + .unwrap(); + + log::debug!("state trie {:?}", state_trie); + } + #[cfg(test)] if KERNEL.offset_name(pc) == "smt_hash_state" || KERNEL.offset_name(pc) == "sys_sstore" { let mem = state diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index 8bac6c2ae..65d47b2dd 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -255,6 +255,7 @@ fn token_storage_after() -> anyhow::Result { } fn giver_account() -> anyhow::Result { + log::debug!("giver bytecode {:?}", giver_bytecode()); Ok(MptAccountRlp { nonce: 1.into(), balance: 0.into(), From 9fa96a02e7ea201aa230eebbfaeb61facaa89826 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 7 Nov 2024 09:58:59 +0100 Subject: [PATCH 49/60] Fix beacon root storage keys --- .../src/cpu/kernel/asm/beacon_roots.asm | 20 +++++++++---------- evm_arithmetization/src/generation/mpt.rs | 2 ++ evm_arithmetization/src/testing_utils.rs | 11 +++++++++- evm_arithmetization/tests/simple_transfer.rs | 2 ++ mpt_trie/src/trie_hashing.rs | 1 + 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm index a08939b3f..f35e875b9 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm @@ -15,23 +15,19 @@ global set_beacon_root: // stack: timestamp, 8191, timestamp, retdest MOD // stack: timestamp_idx, timestamp, retdest - %slot_to_storage_key - // stack: timestamp_slot_key, timestamp, retdest PUSH @BEACON_ROOTS_CONTRACT_STATE_KEY %parent_beacon_block_root - // stack: calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: calldata, state_key, ttimestamp_idx, timestamp, retdest PUSH @HISTORY_BUFFER_LENGTH DUP5 MOD - // stack: timestamp_idx, calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: timestamp_idx, calldata, state_key, timestamp_idx, timestamp, retdest %add_const(@HISTORY_BUFFER_LENGTH) - // stack: root_idx, calldata, state_key, timestamp_slot_key, timestamp, retdest - %slot_to_storage_key - // stack: root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: root_idx, calldata, state_key, timestamp_idx, timestamp, retdest DUP3 - // stack: state_key, root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, retdest + // stack: state_key, root_idx, calldata, state_key, timestamp_idx, timestamp, retdest DUP3 ISZERO %jumpi(delete_root_idx_slot) - // stack: state_key, root_slot_key, calldata, state_key, timestamp_slot_key, timestamp, + // stack: state_key, root_idx, calldata, state_key, timestamp_idx, timestamp, global debug_inserting_first_slot: %insert_slot_from_addr_key // stack: state_key, timestamp_idx, timestamp, retdest @@ -40,15 +36,17 @@ global debug_inserting_second_slot: // stack: retdest JUMP +global debug_delete_root_idx_slot: delete_root_idx_slot: - // stack: state_key, root_slot_idx, 0, state_key, timestamp_idx, timestamp, retdest + // stack: state_key, root_idx, calldata, state_key, timestamp_idx, timestamp, retdest DUP2 DUP2 %search_slot_from_addr_key // stack: slot_exists, state_key, root_slot_idx, 0, state_key, timestamp_idx, timestamp, retdest %jumpi(remove_root_idx_slot) - // stack: state_key, root_slot_key, 0, state_key, timestamp_idx, timestamp, retdest + // stack: state_key, root_idx, 0, state_key, timestamp_idx, timestamp, retdest %pop3 // stack: state_key, timestamp_idx, timestamp, retdest +global debug_inserting_timestamp_slot: %insert_slot_from_addr_key // stack: retdest JUMP diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index c3199c2f1..63104bcf2 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -692,6 +692,8 @@ where .try_into() .map_err(|_| ProgramError::IntegerTooLarge)?; storage_leaves.push(Some(slot_key)); + + log::debug!("pushing keys {:?} and {:?}", addr_key, slot_key); // Write `value_ptr_ptr`. let leaves = parse_value(value)? .into_iter() diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index 06f1bb82f..b2ce97146 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -93,6 +93,7 @@ fn insert_storage(trie: &mut HashedPartialTrie, slot: U256, value: U256) -> anyh let mut bytes = [0; 32]; slot.to_big_endian(&mut bytes); let key = keccak(bytes); + log::debug!("slot key = {:?}", key); let nibbles = Nibbles::from_bytes_be(key.as_bytes()).unwrap(); if value.is_zero() { trie.delete(nibbles)?; @@ -123,13 +124,21 @@ pub fn update_beacon_roots_account_storage( let timestamp_idx = timestamp % HISTORY_BUFFER_LENGTH.value; let root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH.value; + log::debug!("inseting timestamp = {:?} and root = {:?}", timestamp, h2u(parent_root)); + log::debug!("initial storage trie = {:?}", storage_trie); + insert_storage(storage_trie, timestamp_idx, timestamp)?; - insert_storage(storage_trie, root_idx, h2u(parent_root)) + insert_storage(storage_trie, root_idx, h2u(parent_root))?; + + log::debug!("storage trie = {:?}", storage_trie); + + Ok(()) } /// Returns the beacon roots contract account from its provided storage trie. #[cfg(feature = "eth_mainnet")] pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { + log::debug!("hashing beacon roots"); MptAccountRlp { storage_root: storage_trie.hash(), ..BEACON_ROOTS_ACCOUNT diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index 8d28bd3a1..a92fe3747 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -99,6 +99,8 @@ fn test_simple_transfer() -> anyhow::Result<()> { let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); + log::debug!("beacon roots expected account:: {:?}", beacon_roots_account); + let sender_account_after = MptAccountRlp { balance: sender_account_before.balance - value - gas_used * 10, nonce: sender_account_before.nonce + 1, diff --git a/mpt_trie/src/trie_hashing.rs b/mpt_trie/src/trie_hashing.rs index c5e4a5ba7..451767363 100644 --- a/mpt_trie/src/trie_hashing.rs +++ b/mpt_trie/src/trie_hashing.rs @@ -90,6 +90,7 @@ fn append_to_stream(s: &mut RlpStream, node: EncodedNode) { } fn hash_bytes(bytes: &Bytes) -> [u8; 32] { + log::debug!("hashing bytes = {:?}", bytes.as_ref()); keccak(bytes).0 } From 21e62aadf0cde4c2a09378e4e303b25dc0e10b1b Mon Sep 17 00:00:00 2001 From: hratoanina Date: Thu, 7 Nov 2024 09:14:55 -0500 Subject: [PATCH 50/60] Fix trie data preinitialization --- evm_arithmetization/src/generation/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 707d97b0d..acd0f5290 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -424,7 +424,7 @@ impl GenerationState { let txn_root_ptr = load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); let receipt_root_ptr = - load_receipts_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); + load_receipts_mpt(&trie_inputs.receipts_trie, &mut trie_data).unwrap(); self.memory.insert_preinitialized_segment( Segment::TrieData, crate::witness::memory::MemorySegmentState { content: trie_data }, From 5b893cdc8d6c0be83a09ef1b97d40560cd73670d Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 7 Nov 2024 09:21:11 -0500 Subject: [PATCH 51/60] Fix compile --- .../src/cpu/kernel/asm/beacon_roots.asm | 2 +- evm_arithmetization/src/witness/transition.rs | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm index f35e875b9..24d3b173b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm @@ -17,7 +17,7 @@ global set_beacon_root: // stack: timestamp_idx, timestamp, retdest PUSH @BEACON_ROOTS_CONTRACT_STATE_KEY %parent_beacon_block_root - // stack: calldata, state_key, ttimestamp_idx, timestamp, retdest + // stack: calldata, state_key, timestamp_idx, timestamp, retdest PUSH @HISTORY_BUFFER_LENGTH DUP5 MOD diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 65165b1f2..b0e1d803d 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -13,7 +13,7 @@ use crate::cpu::kernel::constants::MAX_CODE_SIZE; use crate::cpu::kernel::opcodes::get_opcode; #[cfg(test)] use crate::cpu::kernel::tests::mpt::linked_list::StateLinkedList; -#[cfg(test)] +#[cfg(all(test, not(feature = "cdk_erigon")))] use crate::cpu::kernel::tests::mpt::linked_list::{AccountsLinkedList, StorageLinkedList}; use crate::cpu::membus::NUM_GP_CHANNELS; use crate::cpu::stack::{ @@ -21,6 +21,7 @@ use crate::cpu::stack::{ }; use crate::generation::linked_list::testing::LinkedList; use crate::generation::state::State; +#[cfg(not(feature = "cdk_erigon"))] use crate::generation::trie_extractor::get_state_trie; use crate::memory::segments::Segment; // TO REMOVE! @@ -320,14 +321,18 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ), ); - - // #[cfg(test)] + #[cfg(all(test, not(feature = "cdk_erigon")))] if KERNEL.offset_name(pc) == "mpt_hash_state_trie" || KERNEL.offset_name(pc) == "init" { let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::TrieData); - log::debug!("account nonce = {:?} balance {:?} code hash {:?}", mem[5], mem[6], mem[8]); + .get_generation_state() + .memory + .get_preinit_memory(Segment::TrieData); + log::debug!( + "account nonce = {:?} balance {:?} code hash {:?}", + mem[5], + mem[6], + mem[8] + ); let mem = state .get_generation_state() .memory From afe39b046a41ea1e2a5e1fdf007393db69944474 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Thu, 7 Nov 2024 17:19:04 +0100 Subject: [PATCH 52/60] Fix sstore --- .../kernel/asm/linked_list/final_tries.asm | 3 ++ .../kernel/asm/linked_list/initial_tries.asm | 1 + .../src/cpu/kernel/tests/account_code.rs | 3 +- evm_arithmetization/src/generation/mpt.rs | 33 +++++++++++++------ evm_arithmetization/src/generation/state.rs | 16 +++++++-- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm index 610ba3a2e..3cfd798b4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/final_tries.asm @@ -122,7 +122,9 @@ global delete_removed_accounts: %add_const(2) MLOAD_GENERAL // get initial payload_ptr %add_const(2) // storage_root_ptr_ptr = payload_ptr + 2 +global debug_loading_storage_root_ptr: %mload_trie_data +global debug_storage_root_ptr: // stack: storage_root_ptr, key, account_ptr_ptr, root_ptr, storage_ptr_ptr, retdest DUP3 %increment @@ -167,6 +169,7 @@ after_mpt_delete: // Pre stack: addr, root_ptr, storage_ptr_ptr, retdest // Post stack: new_root_ptr, storage_ptr_ptr'. delete_removed_slots: +global debug_delete_removed_slots: // stack: addr, root_ptr, storage_ptr_ptr, retdest DUP3 MLOAD_GENERAL diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm index cc95cdb58..adb8ae468 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm @@ -46,6 +46,7 @@ after_mpt_read: %mload_trie_data %add_const(2) %mload_trie_data +global debug_trie_storage_root: // stack: trie_storage_root, trie_account_ptr_ptr, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest SWAP1 // stack: trie_account_ptr_ptr, trie_storage_root, key, storage_ptr_ptr, root_ptr, account_ptr_ptr, retdest diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index a883102e8..ea58107a1 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -530,7 +530,7 @@ fn sstore() -> Result<()> { let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert(addr_nibbles, account_before.rlp_encode().to_vec())?; - let state_trie = get_state_world(state_trie_before, vec![]); + let state_trie = get_state_world(state_trie_before, vec![(addr_hashed, HashedPartialTrie::from(Node::Empty))]);// storage tries is empty but should contain empty tries? let trie_inputs = TrieInputs { state_trie, @@ -595,6 +595,7 @@ fn sstore() -> Result<()> { interpreter .push(1.into()) // Initial length of the trie data segment, unused. .expect("The stack should not overflow"); + log::debug!("donde estas satanas"); interpreter.run()?; Ok(()) diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 63104bcf2..371f4218c 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -342,7 +342,9 @@ where { let node_ptr = trie_data.len(); let type_of_trie = PartialTrieType::of(trie) as u32; + log::debug!("el trie = {:?}", trie); if type_of_trie > 0 { + log::debug!("writting {:?} in {:?}", type_of_trie, trie_data.len()); trie_data.push(Some(type_of_trie.into())); } @@ -487,6 +489,7 @@ fn load_state_trie( .get(&merged_key) .copied() .unwrap_or(&storage_hash_only); + log::debug!("storage tries = {:?}", storage_tries_by_state_key); assert_eq!(storage_trie.hash(), storage_root, "In TrieInputs, an account's storage_root didn't match the associated storage trie hash"); @@ -504,11 +507,14 @@ fn load_state_trie( trie_data.push(Some(balance)); // Storage trie ptr. let storage_ptr_ptr = trie_data.len(); + log::debug!("pushing storage_ptr = {:?}", storage_ptr_ptr + 2); trie_data.push(Some((trie_data.len() + 2).into())); trie_data.push(Some(code_hash.into_uint())); // We don't need to store the slot values, as they will be overwritten in // `mpt_set_payload`. + log::debug!("loading storage"); let storage_ptr = load_mpt(storage_trie, trie_data, &parse_storage_value_no_return)?; + log::debug!("storage_ptr = {storage_ptr}"); if storage_ptr == 0 { trie_data[storage_ptr_ptr] = Some(0.into()); } @@ -613,7 +619,12 @@ fn get_state_and_storage_leaves( // Push the payload in the trie data. trie_data.push(Some(nonce)); - log::debug!("key = {:?} nonce = {:?} balance= {:?}", addr_key, nonce, balance); + log::debug!( + "key = {:?} nonce = {:?} balance= {:?}", + addr_key, + nonce, + balance + ); trie_data.push(Some(balance)); // The Storage pointer is only written in the trie. trie_data.push(Some(0.into())); @@ -794,15 +805,17 @@ pub(crate) fn load_state_mpt( trie_data: &mut Vec>, ) -> Result { let storage_tries_by_state_key = match &trie_inputs.state_trie.state { - Either::Left(mpt) => mpt - .get_storage() - .iter() - .map(|(hashed_address, storage_trie)| { - let key = Nibbles::from_bytes_be(hashed_address.as_bytes()) - .expect("An H256 is 32 bytes long"); - (key, *storage_trie) - }) - .collect::>(), + Either::Left(mpt) => { + log::debug!("el mundo = {:?}", mpt); + mpt.get_storage() + .iter() + .map(|(hashed_address, storage_trie)| { + let key = Nibbles::from_bytes_be(hashed_address.as_bytes()) + .expect("An H256 is 32 bytes long"); + (key, *storage_trie) + }) + .collect::>() + } Either::Right(_) => unreachable!("eth_mainnet expects an MPT."), }; diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 707d97b0d..db9f0eece 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -221,6 +221,18 @@ pub(crate) trait State { "initial state linked list = {:?}", StateLinkedList::from_mem_and_segment(&mem, Segment::AccountsLinkedList) ); + #[cfg(not(feature = "cdk_erigon"))] + { + use crate::cpu::kernel::tests::mpt::linked_list::StorageLinkedList; + let mem = self + .get_generation_state() + .memory + .get_preinit_memory(Segment::StorageLinkedList); + log::debug!( + "initial storage linked list = {:?}", + StorageLinkedList::from_mem_and_segment(&mem, Segment::StorageLinkedList) + ); + } } loop { @@ -351,13 +363,13 @@ pub(crate) trait State { /// Logs `msg` in `debug` mode. #[inline] fn log_debug(&self, msg: String) { - log::debug!("{}", msg); + // log::debug!("{}", msg); } /// Logs `msg` at `level`. #[inline] fn log(&self, level: Level, msg: String) { - log::log!(level, "{}", msg); + // log::log!(level, "{}", msg); } } From 8db31fec374b5bbcd45542be5de92894c8e30678 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 7 Nov 2024 13:55:45 -0500 Subject: [PATCH 53/60] Refactor types --- .../benches/fibonacci_25m_gas.rs | 82 +++--- .../cpu/kernel/asm/core/create_receipt.asm | 8 +- .../src/cpu/kernel/constants/mod.rs | 8 +- .../src/cpu/kernel/tests/account_code.rs | 80 +++--- .../src/cpu/kernel/tests/add11.rs | 240 ++++++++---------- .../src/cpu/kernel/tests/balance.rs | 36 ++- .../src/cpu/kernel/tests/mpt/delete.rs | 4 +- .../src/cpu/kernel/tests/mpt/insert.rs | 4 +- .../src/cpu/kernel/tests/mpt/mod.rs | 44 ++-- .../src/cpu/kernel/tests/receipt.rs | 2 +- .../transaction_parsing/parse_type_3_txn.rs | 30 +-- evm_arithmetization/src/generation/mpt.rs | 81 +++--- .../src/generation/trie_extractor.rs | 4 +- evm_arithmetization/src/testing_utils.rs | 20 +- evm_arithmetization/src/witness/transition.rs | 1 + evm_arithmetization/src/world/tries.rs | 14 +- evm_arithmetization/src/world/type1.rs | 4 +- evm_arithmetization/src/world/world.rs | 4 +- evm_arithmetization/tests/add11_yml.rs | 102 +++----- evm_arithmetization/tests/erc20.rs | 22 +- evm_arithmetization/tests/erc20_type2.rs | 24 +- evm_arithmetization/tests/erc721.rs | 14 +- evm_arithmetization/tests/log_opcode.rs | 30 +-- evm_arithmetization/tests/selfdestruct.rs | 10 +- evm_arithmetization/tests/simple_transfer.rs | 10 +- evm_arithmetization/tests/withdrawals.rs | 6 +- mpt_trie/src/debug_tools/diff.rs | 12 +- trace_decoder/src/core.rs | 2 +- zero/src/trie_diff/mod.rs | 4 +- 29 files changed, 407 insertions(+), 495 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index e2eea3ada..5ddffd8c9 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -16,8 +16,8 @@ use ethereum_types::{Address, BigEndianHash, H256, U256}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; use evm_arithmetization::generation::mpt::{ - get_h256_from_code_hash, get_u256_from_code_hash, AccountRlp, CodeHashType, EitherRlp, - LegacyReceiptRlp, MptAccountRlp, + get_h256_from_code_hash, get_u256_from_code_hash, Account, CodeHashType, EitherAccount, + LegacyReceiptRlp, MptAccount, }; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; @@ -96,14 +96,14 @@ fn prepare_setup() -> anyhow::Result> { let empty_trie_root = HashedPartialTrie::from(Node::Empty).hash(); let sender_account_before = if cfg!(feature = "cdk_erigon") { - Either::Right(SmtAccountRlp { + Either::Right(SmtAccount { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, code_hash: hash_bytecode_u256(vec![]), code_length: 0.into(), }) } else { - Either::Left(MptAccountRlp { + Either::Left(MptAccount { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, storage_root: empty_trie_root, @@ -112,25 +112,21 @@ fn prepare_setup() -> anyhow::Result> { }; let to_account_before = if cfg!(feature = "cdk_erigon") { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: 1.into(), - balance: 0.into(), - code_hash: get_u256_from_code_hash(code_hash.clone()) - .expect("In cdk_erigon, the code_hash is a U256"), - code_length: code.len().into(), - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: 1.into(), + balance: 0.into(), + code_hash: get_u256_from_code_hash(code_hash.clone()) + .expect("In cdk_erigon, the code_hash is a U256"), + code_length: code.len().into(), + })) } else { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - balance: 0.into(), - storage_root: empty_trie_root, - code_hash: get_h256_from_code_hash(code_hash.clone()) - .expect("In eth_mainnet, the code_hash is a H256"), - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + balance: 0.into(), + storage_root: empty_trie_root, + code_hash: get_h256_from_code_hash(code_hash.clone()) + .expect("In eth_mainnet, the code_hash is a H256"), + })) }; let mut state_trie_before = StateWorld::default(); @@ -158,7 +154,7 @@ fn prepare_setup() -> anyhow::Result> { { let sender_account_before_smt = sender_account_before.expect_right("The sender account is an SMT."); - let to_account_before_smt = to_account_before.as_smt_account_rlp(); + let to_account_before_smt = to_account_before.as_smt_account(); set_account( &mut state_trie_before, H160(sender), @@ -214,27 +210,23 @@ fn prepare_setup() -> anyhow::Result> { let sender_account_after = if cfg!(feature = "cdk_erigon") { let sender_account_before_smt = sender_account_before.expect_right("cdk_erigon expects SMTs."); - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: sender_account_before_smt.get_balance() - - value - - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before_smt.get_nonce() + 1, - ..sender_account_before_smt - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: sender_account_before_smt.get_balance() + - value + - gas_used * block_metadata.block_base_fee, + nonce: sender_account_before_smt.get_nonce() + 1, + ..sender_account_before_smt + })) } else { let sender_account_before_mpt = sender_account_before.expect_left("eth_mainnet expects MPTs."); - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: sender_account_before_mpt.get_balance() - - value - - gas_used * block_metadata.block_base_fee, - nonce: sender_account_before_mpt.get_nonce() + 1, - ..sender_account_before_mpt - }), - } + EitherAccount(Either::Left(MptAccount { + balance: sender_account_before_mpt.get_balance() + - value + - gas_used * block_metadata.block_base_fee, + nonce: sender_account_before_mpt.get_nonce() + 1, + ..sender_account_before_mpt + })) }; let to_account_after = &to_account_before; @@ -264,8 +256,8 @@ fn prepare_setup() -> anyhow::Result> { #[cfg(feature = "cdk_erigon")] { - let sender_account_after_smt = sender_account_after.as_smt_account_rlp(); - let to_account_after_smt = to_account_after.as_smt_account_rlp(); + let sender_account_after_smt = sender_account_after.as_smt_account(); + let to_account_after_smt = to_account_after.as_smt_account(); set_account( &mut expected_state_trie_after, H160(sender), @@ -348,10 +340,10 @@ fn init_logger() { criterion_group!(benches, criterion_benchmark); criterion_main!(benches); -use evm_arithmetization::generation::mpt::SmtAccountRlp; +use evm_arithmetization::generation::mpt::SmtAccount; #[cfg(feature = "cdk_erigon")] -fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccountRlp, code: &[u8]) { +fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccount, code: &[u8]) { use evm_arithmetization::world::world::World; let key = key_balance(addr); diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm index edcd3f329..2c5d24f61 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_receipt.asm @@ -1,13 +1,13 @@ // Pre-stack: status, leftover_gas, prev_cum_gas, txn_nb, num_nibbles, retdest // Post stack: new_cum_gas, txn_nb -// A receipt is stored in MPT_TRIE_DATA as: +// A receipt is stored in TRIE_DATA as: // [payload_len, status, cum_gas_used, bloom, logs_payload_len, num_logs, [logs]] // // In this function, we: // - compute cum_gas, // - check if the transaction failed and set number of logs to 0 if it is the case, // - compute the bloom filter, -// - write the receipt in MPT_TRIE_DATA , +// - write the receipt in TRIE_DATA , // - insert a new node in receipt_trie, // - set the bloom filter back to 0 global process_receipt: @@ -51,7 +51,7 @@ process_receipt_after_bloom: %rlp_list_len ADD // stack: payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest - // Now we can write the receipt in MPT_TRIE_DATA. + // Now we can write the receipt in TRIE_DATA. %get_trie_data_size // stack: receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest // Write transaction type if necessary. @@ -103,7 +103,7 @@ process_receipt_after_type: DUP1 %append_to_trie_data PUSH 0 -// Each log is written in MPT_TRIE_DATA as: +// Each log is written in TRIE_DATA as: // [payload_len, address, num_topics, [topics], data_len, [data]]. process_receipt_logs_loop: // stack: i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 73a730b0d..8e37d9543 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -430,7 +430,7 @@ const LINKED_LISTS_CONSTANTS: [(&str, u16); 8] = [ pub mod cancun_constants { use super::*; - use crate::generation::mpt::MptAccountRlp; + use crate::generation::mpt::MptAccount; pub const BLOB_BASE_FEE_UPDATE_FRACTION: U256 = U256([0x32f0ed, 0, 0, 0]); @@ -477,7 +477,7 @@ pub mod cancun_constants { pub const BEACON_ROOTS_CONTRACT_CODE_HASH: [u8; 32] = hex!("f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c"); - pub const BEACON_ROOTS_ACCOUNT: MptAccountRlp = MptAccountRlp { + pub const BEACON_ROOTS_ACCOUNT: MptAccount = MptAccount { nonce: U256::zero(), balance: U256::zero(), // Storage root for this account at genesis. @@ -498,7 +498,7 @@ pub mod cancun_constants { pub mod global_exit_root { use super::*; - use crate::generation::mpt::MptAccountRlp; + use crate::generation::mpt::MptAccount; /// Taken from . pub const GLOBAL_EXIT_ROOT_MANAGER_L2: (&str, [u8; 20]) = ( @@ -540,7 +540,7 @@ pub mod global_exit_root { pub const GLOBAL_EXIT_ROOT_CONTRACT_CODE_HASH: [u8; 32] = hex!("6bec2bf64f7e824109f6ed55f77dd7665801d6195e461666ad6a5342a9f6daf5"); - pub const GLOBAL_EXIT_ROOT_ACCOUNT: MptAccountRlp = MptAccountRlp { + pub const GLOBAL_EXIT_ROOT_ACCOUNT: MptAccount = MptAccount { nonce: U256::zero(), balance: U256::zero(), // Empty storage root diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index a883102e8..dc329fc8f 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -21,7 +21,7 @@ use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; #[cfg(not(feature = "cdk_erigon"))] use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; -use crate::generation::mpt::{load_state_mpt, AccountRlp, EitherRlp, MptAccountRlp, SmtAccountRlp}; +use crate::generation::mpt::{load_state_mpt, Account, EitherAccount, MptAccount, SmtAccount}; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -157,7 +157,7 @@ pub(crate) fn initialize_mpts( pub(crate) fn prepare_interpreter( interpreter: &mut Interpreter, address: Address, - account: &EitherRlp, + account: &EitherAccount, ) -> Result<()> { let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; @@ -267,25 +267,21 @@ pub(crate) fn prepare_interpreter( } // Test account with a given code hash. -fn test_account(code: &[u8]) -> EitherRlp { +fn test_account(code: &[u8]) -> EitherAccount { if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: keccak(code), - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: HashedPartialTrie::from(Node::Empty).hash(), + code_hash: keccak(code), + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - code_hash: hash_bytecode_u256(code.to_vec()), - code_length: code.len().into(), - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: hash_bytecode_u256(code.to_vec()), + code_length: code.len().into(), + })) } } @@ -519,13 +515,11 @@ fn sstore() -> Result<()> { let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; let code_hash = keccak(code); - let account_before = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..MptAccountRlp::default() - }), - }; + let account_before = EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..MptAccount::default() + })); let mut state_trie_before = HashedPartialTrie::from(Node::Empty); @@ -561,18 +555,16 @@ fn sstore() -> Result<()> { // The code should have added an element to the storage of `to_account`. We run // `mpt_hash_state_trie` to check that. - let account_after = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..MptAccountRlp::default() - }), - }; + let account_after = EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..MptAccount::default() + })); let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); expected_state_trie_after.insert(addr_nibbles, account_after.rlp_encode().to_vec())?; @@ -625,13 +617,11 @@ fn sload() -> Result<()> { ]; let code_hash = keccak(code); - let account_before = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..MptAccountRlp::default() - }), - }; + let account_before = EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..MptAccount::default() + })); let mut state_trie_before = HashedPartialTrie::from(Node::Empty); diff --git a/evm_arithmetization/src/cpu/kernel/tests/add11.rs b/evm_arithmetization/src/cpu/kernel/tests/add11.rs index e0c08dc95..e323dec8c 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/add11.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/add11.rs @@ -15,9 +15,7 @@ use smt_trie::code::hash_bytecode_u256; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; -use crate::generation::mpt::{ - AccountRlp, EitherRlp, LegacyReceiptRlp, MptAccountRlp, SmtAccountRlp, -}; +use crate::generation::mpt::{Account, EitherAccount, LegacyReceiptRlp, MptAccount, SmtAccount}; use crate::generation::TrieInputs; use crate::proof::{BlockHashes, BlockMetadata, TrieRoots}; use crate::testing_utils::*; @@ -51,53 +49,41 @@ fn test_add11_yml() { } let beneficiary_account_before = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: 1.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: 1.into(), + ..SmtAccount::default() + })) }; let sender_account_before = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: 0x0de0b6b3a7640000u64.into(), + ..SmtAccount::default() + })) }; let to_account_before = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash: code_hash.expect_right("cdk_erigon uses Poseidon."), - code_length: code.len().into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_right("cdk_erigon uses Poseidon."), + code_length: code.len().into(), + ..SmtAccount::default() + })) }; let (mut state_trie_before, mut storage_tries) = @@ -145,60 +131,48 @@ fn test_add11_yml() { let expected_state_trie_after = { let beneficiary_account_after = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: 1.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: 1.into(), + ..SmtAccount::default() + })) }; let sender_account_after = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0xde0b6b3a75be550u64.into(), - nonce: 1.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: 0xde0b6b3a75be550u64.into(), - nonce: 1.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..SmtAccount::default() + })) }; let to_account_after = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0xde0b6b3a76586a0u64.into(), - code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), - // Storage map: { 0 => 2 } - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), + // Storage map: { 0 => 2 } + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: 0xde0b6b3a76586a0u64.into(), - code_hash: code_hash.expect_right("cdk_erigon uses Keccak."), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash: code_hash.expect_right("cdk_erigon uses Keccak."), + ..SmtAccount::default() + })) }; update_beacon_roots_account_storage( @@ -315,52 +289,40 @@ fn test_add11_yml_with_exception() { } let beneficiary_account_before = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: 1.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: 1.into(), + ..SmtAccount::default() + })) }; let sender_account_before = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: 0x0de0b6b3a7640000u64.into(), + ..SmtAccount::default() + })) }; let to_account_before = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_left("eth_mainnet uses Keccak."), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash: code_hash.expect_right("cdk_erigon uses Poseidon."), - code_length: code.len().into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash: code_hash.expect_right("cdk_erigon uses Poseidon."), + code_length: code.len().into(), + ..SmtAccount::default() + })) }; let (mut state_trie_before, mut storage_tries) = @@ -414,21 +376,17 @@ fn test_add11_yml_with_exception() { let beneficiary_account_after = beneficiary_account_before; // This is the only account that changes: the nonce and the balance are updated. let sender_account_after = if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: sender_account_before.get_balance() - txn_gas_limit * gas_price, - nonce: 1.into(), - ..MptAccountRlp::default() - }), - } + EitherAccount(Either::Left(MptAccount { + balance: sender_account_before.get_balance() - txn_gas_limit * gas_price, + nonce: 1.into(), + ..MptAccount::default() + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - balance: sender_account_before.get_balance() - txn_gas_limit * gas_price, - nonce: 1.into(), - ..SmtAccountRlp::default() - }), - } + EitherAccount(Either::Right(SmtAccount { + balance: sender_account_before.get_balance() - txn_gas_limit * gas_price, + nonce: 1.into(), + ..SmtAccount::default() + })) }; let to_account_after = to_account_before; diff --git a/evm_arithmetization/src/cpu/kernel/tests/balance.rs b/evm_arithmetization/src/cpu/kernel/tests/balance.rs index baaea6302..346a5fe5b 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/balance.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/balance.rs @@ -8,31 +8,27 @@ use rand::{thread_rng, Rng}; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::prepare_interpreter; -use crate::generation::mpt::EitherRlp; -use crate::generation::mpt::MptAccountRlp; -use crate::generation::mpt::SmtAccountRlp; +use crate::generation::mpt::EitherAccount; +use crate::generation::mpt::MptAccount; +use crate::generation::mpt::SmtAccount; use crate::Node; // Test account with a given code hash. -fn test_account(balance: U256) -> EitherRlp { +fn test_account(balance: U256) -> EitherAccount { if cfg!(feature = "eth_mainnet") { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: U256::from(1111), - balance, - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: H256::from_uint(&U256::from(8888)), - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: U256::from(1111), + balance, + storage_root: HashedPartialTrie::from(Node::Empty).hash(), + code_hash: H256::from_uint(&U256::from(8888)), + })) } else { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: U256::from(1111), - balance, - code_hash: U256::from(8888), - code_length: 0.into(), - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: U256::from(1111), + balance, + code_hash: U256::from(8888), + code_length: 0.into(), + })) } } diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs index 9c5abada6..206d4936f 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/delete.rs @@ -11,7 +11,7 @@ use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{nibbles_64, test_account_1_rlp, test_account_2}; -use crate::generation::mpt::MptAccountRlp; +use crate::generation::mpt::MptAccount; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::testing_utils::get_state_world; @@ -87,7 +87,7 @@ fn test_after_mpt_delete_extension_branch() -> Result<()> { fn test_state_trie( state_trie: HashedPartialTrie, k: Nibbles, - mut account: MptAccountRlp, + mut account: MptAccount, ) -> Result<()> { assert_eq!(k.count, 64); diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs index a82170c02..74b55de44 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/insert.rs @@ -15,7 +15,7 @@ use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{ nibbles_64, nibbles_count, test_account_1_rlp, test_account_2, }; -use crate::generation::mpt::MptAccountRlp; +use crate::generation::mpt::MptAccount; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -166,7 +166,7 @@ fn mpt_insert_branch_to_leaf_same_key() -> Result<()> { fn test_state_trie( mut state_trie: HashedPartialTrie, k: Nibbles, - mut account: MptAccountRlp, + mut account: MptAccount, ) -> Result<()> { assert_eq!(k.count, 64); diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index cbe19a8b4..2a1281845 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -4,9 +4,9 @@ use mpt_trie::nibbles::Nibbles; use mpt_trie::partial_trie::HashedPartialTrie; use mpt_trie::partial_trie::PartialTrie; -use crate::generation::mpt::EitherRlp; -use crate::generation::mpt::MptAccountRlp; -use crate::generation::mpt::{AccountRlp, SmtAccountRlp}; +use crate::generation::mpt::EitherAccount; +use crate::generation::mpt::MptAccount; +use crate::generation::mpt::{Account, SmtAccount}; use crate::Node; #[cfg(not(feature = "cdk_erigon"))] @@ -38,31 +38,27 @@ pub(crate) fn nibbles_count>(v: T, count: usize) -> Nibbles { } } -pub(crate) fn test_account_1_empty_storage() -> EitherRlp { +pub(crate) fn test_account_1_empty_storage() -> EitherAccount { if cfg!(feature = "cdk_erigon") { - EitherRlp { - account_rlp: Either::Right(SmtAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - code_hash: U256::from(4444), - code_length: 0.into(), - }), - } + EitherAccount(Either::Right(SmtAccount { + nonce: U256::from(1111), + balance: U256::from(2222), + code_hash: U256::from(4444), + code_length: 0.into(), + })) } else { - EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: U256::from(1111), - balance: U256::from(2222), - storage_root: HashedPartialTrie::from(Node::Empty).hash(), - code_hash: H256::from_uint(&U256::from(4444)), - }), - } + EitherAccount(Either::Left(MptAccount { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: HashedPartialTrie::from(Node::Empty).hash(), + code_hash: H256::from_uint(&U256::from(4444)), + })) } } #[cfg(not(feature = "cdk_erigon"))] -pub(crate) fn test_account_1() -> MptAccountRlp { - MptAccountRlp { +pub(crate) fn test_account_1() -> MptAccount { + MptAccount { nonce: U256::from(1111), balance: U256::from(2222), storage_root: H256::from_uint(&U256::from(3333)), @@ -80,8 +76,8 @@ pub(crate) fn test_account_1_empty_storage_rlp() -> Vec { } #[cfg(not(feature = "cdk_erigon"))] -pub(crate) fn test_account_2() -> MptAccountRlp { - MptAccountRlp { +pub(crate) fn test_account_2() -> MptAccount { + MptAccount { nonce: U256::from(5555), balance: U256::from(6666), storage_root: H256::from_uint(&U256::from(7777)), diff --git a/evm_arithmetization/src/cpu/kernel/tests/receipt.rs b/evm_arithmetization/src/cpu/kernel/tests/receipt.rs index 6482cfd59..34c7a8003 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/receipt.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/receipt.rs @@ -19,7 +19,7 @@ fn test_process_receipt() -> Result<()> { /* Tests process_receipt, which: - computes the cumulative gas - computes the bloom filter - - inserts the receipt data in MPT_TRIE_DATA + - inserts the receipt data in TRIE_DATA - inserts a node in receipt_trie - resets the bloom filter to 0 for the next transaction. */ let process_receipt = KERNEL.global_labels["process_receipt"]; diff --git a/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs b/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs index aa69dc3a9..d605a133c 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/transaction_parsing/parse_type_3_txn.rs @@ -11,20 +11,18 @@ use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::prepare_interpreter; use crate::cpu::kernel::tests::transaction_parsing::prepare_interpreter_for_txn_parsing; -use crate::generation::mpt::{EitherRlp, MptAccountRlp}; +use crate::generation::mpt::{EitherAccount, MptAccount}; use crate::testing_utils::EMPTY_NODE_HASH; #[test] fn process_type_3_txn() -> Result<()> { let sender_address = Address::from_slice(&hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")); - let sender_account = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - balance: 0x1000000.into(), - storage_root: EMPTY_NODE_HASH, - code_hash: H256::default(), - }), - }; + let sender_account = EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + balance: 0x1000000.into(), + storage_root: EMPTY_NODE_HASH, + code_hash: H256::default(), + })); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); // Prepare the interpreter by inserting the sender account in the state trie. @@ -110,14 +108,12 @@ fn process_type_3_txn() -> Result<()> { #[test] fn process_type_3_txn_invalid_sig() -> Result<()> { let sender_address = Address::from_slice(&hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")); - let sender_account = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - balance: 0x1000000.into(), - storage_root: EMPTY_NODE_HASH, - code_hash: H256::default(), - }), - }; + let sender_account = EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + balance: 0x1000000.into(), + storage_root: EMPTY_NODE_HASH, + code_hash: H256::default(), + })); let mut interpreter: Interpreter = Interpreter::new(0, vec![], None); // Prepare the interpreter by inserting the sender account in the state trie. diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 63104bcf2..2e01d5afe 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -45,14 +45,14 @@ pub fn get_u256_from_code_hash(code_hash: CodeHashType) -> Option { } #[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct MptAccountRlp { +pub struct MptAccount { pub nonce: U256, pub balance: U256, pub storage_root: H256, pub code_hash: H256, } -impl AccountRlp for MptAccountRlp { +impl Account for MptAccount { fn get_nonce(&self) -> U256 { self.nonce } @@ -76,15 +76,15 @@ impl AccountRlp for MptAccountRlp { } } -#[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct SmtAccountRlp { +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct SmtAccount { pub nonce: U256, pub balance: U256, pub code_length: U256, pub code_hash: U256, } -impl AccountRlp for SmtAccountRlp { +impl Account for SmtAccount { fn get_nonce(&self) -> U256 { self.nonce } @@ -104,11 +104,11 @@ impl AccountRlp for SmtAccountRlp { self.code_hash } fn rlp_encode(&self) -> BytesMut { - rlp::encode(self) + unimplemented!("SMTs do not support RLP encoding.") } } -pub trait AccountRlp: Any { +pub trait Account: Any { fn get_nonce(&self) -> U256; fn get_balance(&self) -> U256; fn get_storage_root(&self) -> H256; @@ -118,88 +118,84 @@ pub trait AccountRlp: Any { fn rlp_encode(&self) -> BytesMut; } -pub struct EitherRlp { - pub account_rlp: Either, -} +pub struct EitherAccount(pub Either); -impl EitherRlp { +impl EitherAccount { #[cfg(test)] pub(crate) fn rlp_encode(&self) -> BytesMut { - match &self.account_rlp { + match &self.0 { Either::Left(mpt_acct) => mpt_acct.rlp_encode(), Either::Right(smt_acct) => smt_acct.rlp_encode(), } } - pub fn as_smt_account_rlp(&self) -> &SmtAccountRlp { - match &self.account_rlp { + pub fn as_smt_account(&self) -> &SmtAccount { + match &self.0 { Either::Left(_mpt_account_rlp) => panic!("cdk_erigon expects SMTs"), Either::Right(smt_account_rlp) => smt_account_rlp, } } - pub fn as_mpt_account_rlp(&self) -> &MptAccountRlp { - match &self.account_rlp { + pub fn as_mpt_account(&self) -> &MptAccount { + match &self.0 { Either::Left(mpt_account_rlp) => mpt_account_rlp, Either::Right(_smt_account_rlp) => panic!("eth_main expects MPTs"), } } } -impl AccountRlp for EitherRlp { +impl Account for EitherAccount { fn get_nonce(&self) -> U256 { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_nonce(), Either::Right(smt_rlp) => smt_rlp.get_nonce(), } } fn get_balance(&self) -> U256 { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_balance(), Either::Right(smt_rlp) => smt_rlp.get_balance(), } } fn get_storage_root(&self) -> H256 { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_storage_root(), Either::Right(smt_rlp) => smt_rlp.get_storage_root(), } } fn get_code_length(&self) -> U256 { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_code_length(), Either::Right(smt_rlp) => smt_rlp.get_code_length(), } } fn get_code_hash(&self) -> CodeHashType { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_code_hash(), Either::Right(smt_rlp) => smt_rlp.get_code_hash(), } } fn get_code_hash_u256(&self) -> U256 { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_code_hash_u256(), Either::Right(smt_rlp) => smt_rlp.get_code_hash_u256(), } } fn rlp_encode(&self) -> BytesMut { - match self.account_rlp { + match self.0 { Either::Left(mpt_rlp) => mpt_rlp.rlp_encode(), Either::Right(smt_rlp) => smt_rlp.rlp_encode(), } } } -impl Default for EitherRlp { +impl Default for EitherAccount { fn default() -> Self { - EitherRlp { - account_rlp: if cfg!(feature = "cdk_erigon") { - Either::Right(SmtAccountRlp::default()) - } else { - Either::Left(MptAccountRlp::default()) - }, - } + EitherAccount(if cfg!(feature = "cdk_erigon") { + Either::Right(SmtAccount::default()) + } else { + Either::Left(MptAccount::default()) + }) } } @@ -210,7 +206,7 @@ pub struct TrieRootPtrs { pub receipt_root_ptr: usize, } -impl Default for MptAccountRlp { +impl Default for MptAccount { fn default() -> Self { Self { nonce: U256::zero(), @@ -221,7 +217,7 @@ impl Default for MptAccountRlp { } } -impl Default for SmtAccountRlp { +impl Default for SmtAccount { fn default() -> Self { use smt_trie::code::hash_bytecode_u256; @@ -472,9 +468,8 @@ fn load_state_trie( Ok(node_ptr) } Node::Leaf { nibbles, value } => { - let account: MptAccountRlp = - rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; - let MptAccountRlp { + let account: MptAccount = rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; + let MptAccount { nonce, balance, storage_root, @@ -573,9 +568,8 @@ fn get_state_and_storage_leaves( Ok(()) } Node::Leaf { nibbles, value } => { - let account: MptAccountRlp = - rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; - let MptAccountRlp { + let account: MptAccount = rlp::decode(value).map_err(|_| ProgramError::InvalidRlp)?; + let MptAccount { nonce, balance, storage_root, @@ -613,7 +607,12 @@ fn get_state_and_storage_leaves( // Push the payload in the trie data. trie_data.push(Some(nonce)); - log::debug!("key = {:?} nonce = {:?} balance= {:?}", addr_key, nonce, balance); + log::debug!( + "key = {:?} nonce = {:?} balance= {:?}", + addr_key, + nonce, + balance + ); trie_data.push(Some(balance)); // The Storage pointer is only written in the trie. trie_data.push(Some(0.into())); diff --git a/evm_arithmetization/src/generation/trie_extractor.rs b/evm_arithmetization/src/generation/trie_extractor.rs index 342167543..e292fc38e 100644 --- a/evm_arithmetization/src/generation/trie_extractor.rs +++ b/evm_arithmetization/src/generation/trie_extractor.rs @@ -94,13 +94,13 @@ pub(crate) fn read_state_rlp_value( memory: &MemoryState, slice: &MemoryValues, ) -> Result, ProgramError> { - use super::mpt::MptAccountRlp; + use super::mpt::MptAccount; let storage_trie: HashedPartialTrie = get_trie(memory, slice[2].unwrap_or_default().as_usize(), |_, x| { Ok(rlp::encode(&read_storage_trie_value(x)).to_vec()) })?; - let account = MptAccountRlp { + let account = MptAccount { nonce: slice[0].unwrap_or_default(), balance: slice[1].unwrap_or_default(), storage_root: storage_trie.hash(), diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index b2ce97146..f7b00baec 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -20,7 +20,7 @@ use starky::config::StarkConfig; pub use crate::cpu::kernel::cancun_constants::*; pub use crate::cpu::kernel::constants::global_exit_root::*; -use crate::generation::mpt::MptAccountRlp; +use crate::generation::mpt::MptAccount; use crate::proof::TrieRoots; #[cfg(test)] use crate::witness::operation::Operation; @@ -124,7 +124,11 @@ pub fn update_beacon_roots_account_storage( let timestamp_idx = timestamp % HISTORY_BUFFER_LENGTH.value; let root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH.value; - log::debug!("inseting timestamp = {:?} and root = {:?}", timestamp, h2u(parent_root)); + log::debug!( + "inseting timestamp = {:?} and root = {:?}", + timestamp, + h2u(parent_root) + ); log::debug!("initial storage trie = {:?}", storage_trie); insert_storage(storage_trie, timestamp_idx, timestamp)?; @@ -137,9 +141,9 @@ pub fn update_beacon_roots_account_storage( /// Returns the beacon roots contract account from its provided storage trie. #[cfg(feature = "eth_mainnet")] -pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { +pub fn beacon_roots_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccount { log::debug!("hashing beacon roots"); - MptAccountRlp { + MptAccount { storage_root: storage_trie.hash(), ..BEACON_ROOTS_ACCOUNT } @@ -216,16 +220,16 @@ pub fn update_scalable_account_storage( } #[cfg(feature = "cdk_erigon")] -pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { - MptAccountRlp { +pub fn ger_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccount { + MptAccount { storage_root: storage_trie.hash(), ..GLOBAL_EXIT_ROOT_ACCOUNT } } #[cfg(feature = "cdk_erigon")] -pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccountRlp { - MptAccountRlp { +pub fn scalable_contract_from_storage(storage_trie: &HashedPartialTrie) -> MptAccount { + MptAccount { storage_root: storage_trie.hash(), ..Default::default() } diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index b0e1d803d..3a1ecd2f7 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -294,6 +294,7 @@ pub(crate) const fn might_overflow_op(op: Operation) -> bool { } pub(crate) fn log_kernel_instruction>(state: &mut S, op: Operation) { + // TODO: Revert // The logic below is a bit costly, so skip it if debug logs aren't enabled. // if !log_enabled!(log::Level::Debug) { // return; diff --git a/evm_arithmetization/src/world/tries.rs b/evm_arithmetization/src/world/tries.rs index e654f8c31..5b1dc1a29 100644 --- a/evm_arithmetization/src/world/tries.rs +++ b/evm_arithmetization/src/world/tries.rs @@ -11,7 +11,7 @@ use mpt_trie::partial_trie::{HashedPartialTrie, Node, OnOrphanedHashNode, Partia use serde::{Deserialize, Serialize}; use u4::{AsNibbles, U4}; -use crate::generation::mpt::MptAccountRlp; +use crate::generation::mpt::MptAccount; /// Bounded sequence of [`U4`], /// used as a key for [MPT](HashedPartialTrie) types in this module. @@ -272,12 +272,12 @@ impl From for HashedPartialTrie { } } -/// Global, [`Address`] `->` [`AccountRlp`]. +/// Global, [`Address`] `->` [`Account`]. /// /// See #[derive(Debug, Clone, Serialize, Deserialize)] pub struct StateMpt { - /// Values are always [`rlp`]-encoded [`AccountRlp`], + /// Values are always [`rlp`]-encoded [`Account`], /// inserted at [256 bits](MptKey::from_hash). inner: HashedPartialTrie, } @@ -289,7 +289,7 @@ impl Default for StateMpt { } #[track_caller] -fn assert_rlp_account(bytes: impl AsRef<[u8]>) -> MptAccountRlp { +fn assert_rlp_account(bytes: impl AsRef<[u8]>) -> MptAccount { rlp::decode(bytes.as_ref()).expect("invalid RLP in StateMPT") } @@ -317,13 +317,13 @@ impl StateMpt { pub fn insert_hash(&mut self, key: MptKey, hash: H256) -> anyhow::Result<()> { Ok(self.inner.insert(key.into_nibbles(), hash)?) } - pub fn insert(&mut self, key: H256, account: MptAccountRlp) -> anyhow::Result<()> { + pub fn insert(&mut self, key: H256, account: MptAccount) -> anyhow::Result<()> { Ok(self.inner.insert( MptKey::from_hash(key).into_nibbles(), rlp::encode(&account).to_vec(), )?) } - pub fn get(&self, key: H256) -> Option { + pub fn get(&self, key: H256) -> Option { self.inner .get(MptKey::from_hash(key).into_nibbles()) .map(assert_rlp_account) @@ -345,7 +345,7 @@ impl StateMpt { self.inner = new; Ok(()) } - pub fn iter(&self) -> impl Iterator + '_ { + pub fn iter(&self) -> impl Iterator + '_ { self.inner.items().filter_map(|(key, rlp)| match rlp { mpt_trie::trie_ops::ValOrHash::Val(vec) => Some(( MptKey::from_nibbles(key).into_hash().expect("bad depth"), diff --git a/evm_arithmetization/src/world/type1.rs b/evm_arithmetization/src/world/type1.rs index 660ad970c..25fed5186 100644 --- a/evm_arithmetization/src/world/type1.rs +++ b/evm_arithmetization/src/world/type1.rs @@ -11,7 +11,7 @@ use mpt_trie::partial_trie::OnOrphanedHashNode; use nunny::NonEmpty; use u4::U4; -use crate::generation::mpt::MptAccountRlp; +use crate::generation::mpt::MptAccount; use crate::world::tries::{MptKey, StateMpt, StorageTrie}; use crate::world::wire::{Instruction, SmtLeaf}; @@ -68,7 +68,7 @@ fn visit( storage, code, }) => { - let account = MptAccountRlp { + let account = MptAccount { nonce: nonce.into(), balance, storage_root: { diff --git a/evm_arithmetization/src/world/world.rs b/evm_arithmetization/src/world/world.rs index 79972a393..cc3128015 100644 --- a/evm_arithmetization/src/world/world.rs +++ b/evm_arithmetization/src/world/world.rs @@ -9,7 +9,7 @@ use mpt_trie::partial_trie::HashedPartialTrie; use serde::{Deserialize, Serialize}; use smt_trie::code::hash_bytecode_u256; -use crate::generation::mpt::AccountRlp; +use crate::generation::mpt::Account; use crate::world::tries::{MptKey, SmtKey, StateMpt, StorageTrie}; #[derive(Clone, Debug, Deserialize, Serialize)] @@ -121,7 +121,7 @@ pub trait World { pub struct Type1World { state: StateMpt, /// Writes to storage should be reconciled with - /// [`storage_root`](evm_arithmetization::generation::mpt::AccountRlp)s. + /// [`storage_root`](evm_arithmetization::generation::mpt::Account)s. storage: BTreeMap, } diff --git a/evm_arithmetization/tests/add11_yml.rs b/evm_arithmetization/tests/add11_yml.rs index 9024b2edd..b0512289b 100644 --- a/evm_arithmetization/tests/add11_yml.rs +++ b/evm_arithmetization/tests/add11_yml.rs @@ -6,9 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; -use evm_arithmetization::generation::mpt::{ - AccountRlp, EitherRlp, LegacyReceiptRlp, MptAccountRlp, -}; +use evm_arithmetization::generation::mpt::{Account, EitherAccount, LegacyReceiptRlp, MptAccount}; use evm_arithmetization::generation::TrieInputs; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -37,7 +35,7 @@ fn get_generation_inputs() -> GenerationInputs { let sender = hex!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b"); let to = hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87"); - let rlp_default = EitherRlp::default(); + let rlp_default = EitherAccount::default(); let beneficiary_state_key = keccak(beneficiary); let sender_state_key = keccak(sender); let to_hashed = keccak(to); @@ -49,25 +47,19 @@ fn get_generation_inputs() -> GenerationInputs { let code = [0x60, 0x01, 0x60, 0x01, 0x01, 0x60, 0x00, 0x55, 0x00]; let code_hash = keccak(code); - let beneficiary_account_before = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - ..*rlp_default.as_mpt_account_rlp() - }), - }; - let sender_account_before = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - ..*rlp_default.as_mpt_account_rlp() - }), - }; - let to_account_before = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0x0de0b6b3a7640000u64.into(), - code_hash, - ..*rlp_default.as_mpt_account_rlp() - }), - }; + let beneficiary_account_before = EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + ..*rlp_default.as_mpt_account() + })); + let sender_account_before = EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + ..*rlp_default.as_mpt_account() + })); + let to_account_before = EitherAccount(Either::Left(MptAccount { + balance: 0x0de0b6b3a7640000u64.into(), + code_hash, + ..*rlp_default.as_mpt_account() + })); let (mut state_trie_before_hashed, mut storage_tries) = preinitialized_state_and_storage_tries().unwrap(); @@ -76,7 +68,7 @@ fn get_generation_inputs() -> GenerationInputs { .insert( beneficiary_nibbles, beneficiary_account_before - .as_mpt_account_rlp() + .as_mpt_account() .rlp_encode() .to_vec(), ) @@ -84,16 +76,13 @@ fn get_generation_inputs() -> GenerationInputs { state_trie_before_hashed .insert( sender_nibbles, - sender_account_before - .as_mpt_account_rlp() - .rlp_encode() - .to_vec(), + sender_account_before.as_mpt_account().rlp_encode().to_vec(), ) .unwrap(); state_trie_before_hashed .insert( to_nibbles, - to_account_before.as_mpt_account_rlp().rlp_encode().to_vec(), + to_account_before.as_mpt_account().rlp_encode().to_vec(), ) .unwrap(); @@ -139,39 +128,33 @@ fn get_generation_inputs() -> GenerationInputs { let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - let beneficiary_account_after = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - nonce: 1.into(), - ..*rlp_default.as_mpt_account_rlp() - }), - }; - let sender_account_after = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0xde0b6b3a75be550u64.into(), - nonce: 1.into(), - ..*rlp_default.as_mpt_account_rlp() - }), - }; - let to_account_after = EitherRlp { - account_rlp: Either::Left(MptAccountRlp { - balance: 0xde0b6b3a76586a0u64.into(), - code_hash, - // Storage map: { 0 => 2 } - storage_root: HashedPartialTrie::from(Node::Leaf { - nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), - value: vec![2], - }) - .hash(), - ..*rlp_default.as_mpt_account_rlp() - }), - }; + let beneficiary_account_after = EitherAccount(Either::Left(MptAccount { + nonce: 1.into(), + ..*rlp_default.as_mpt_account() + })); + let sender_account_after = EitherAccount(Either::Left(MptAccount { + balance: 0xde0b6b3a75be550u64.into(), + nonce: 1.into(), + ..*rlp_default.as_mpt_account() + })); + let to_account_after = EitherAccount(Either::Left(MptAccount { + balance: 0xde0b6b3a76586a0u64.into(), + code_hash, + // Storage map: { 0 => 2 } + storage_root: HashedPartialTrie::from(Node::Leaf { + nibbles: Nibbles::from_h256_be(keccak([0u8; 32])), + value: vec![2], + }) + .hash(), + ..*rlp_default.as_mpt_account() + })); let mut expected_state_trie_after = HashedPartialTrie::from(Node::Empty); expected_state_trie_after .insert( beneficiary_nibbles, beneficiary_account_after - .as_mpt_account_rlp() + .as_mpt_account() .rlp_encode() .to_vec(), ) @@ -179,16 +162,13 @@ fn get_generation_inputs() -> GenerationInputs { expected_state_trie_after .insert( sender_nibbles, - sender_account_after - .as_mpt_account_rlp() - .rlp_encode() - .to_vec(), + sender_account_after.as_mpt_account().rlp_encode().to_vec(), ) .unwrap(); expected_state_trie_after .insert( to_nibbles, - to_account_after.as_mpt_account_rlp().rlp_encode().to_vec(), + to_account_after.as_mpt_account().rlp_encode().to_vec(), ) .unwrap(); expected_state_trie_after diff --git a/evm_arithmetization/tests/erc20.rs b/evm_arithmetization/tests/erc20.rs index 3e72db3dc..b32d65402 100644 --- a/evm_arithmetization/tests/erc20.rs +++ b/evm_arithmetization/tests/erc20.rs @@ -1,11 +1,11 @@ -// #![cfg(feature = "eth_mainnet")] +#![cfg(feature = "eth_mainnet")] use std::str::FromStr; use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -71,7 +71,7 @@ fn test_erc20() -> anyhow::Result<()> { state_trie_before.insert(giver_nibbles, rlp::encode(&giver_account()?).to_vec())?; state_trie_before.insert(token_nibbles, rlp::encode(&token_account()?).to_vec())?; - let account: MptAccountRlp = rlp::decode(&vec![ + let account: MptAccount = rlp::decode(&vec![ 248, 68, 128, 128, 160, 137, 205, 24, 134, 60, 67, 40, 191, 183, 72, 15, 201, 189, 37, 25, 188, 192, 83, 19, 163, 35, 250, 187, 2, 115, 42, 47, 21, 67, 41, 186, 215, 160, 245, 122, 205, 64, 37, 152, 114, 96, 109, 118, 25, 126, 240, 82, 243, 211, 85, 136, 218, 223, 145, @@ -129,14 +129,14 @@ fn test_erc20() -> anyhow::Result<()> { let mut state_trie_after = HashedPartialTrie::from(Node::Empty); let sender_account = sender_account(); - let sender_account_after = MptAccountRlp { + let sender_account_after = MptAccount { nonce: sender_account.nonce + 1, balance: sender_account.balance - gas_used * 0xa, ..sender_account }; state_trie_after.insert(sender_nibbles, rlp::encode(&sender_account_after).to_vec())?; state_trie_after.insert(giver_nibbles, rlp::encode(&giver_account()?).to_vec())?; - let token_account_after = MptAccountRlp { + let token_account_after = MptAccount { storage_root: token_storage_after()?.hash(), ..token_account()? }; @@ -261,9 +261,9 @@ fn token_storage_after() -> anyhow::Result { ]) } -fn giver_account() -> anyhow::Result { +fn giver_account() -> anyhow::Result { log::debug!("giver bytecode {:?}", giver_bytecode()); - Ok(MptAccountRlp { + Ok(MptAccount { nonce: 1.into(), balance: 0.into(), storage_root: giver_storage()?.hash(), @@ -271,8 +271,8 @@ fn giver_account() -> anyhow::Result { }) } -fn token_account() -> anyhow::Result { - Ok(MptAccountRlp { +fn token_account() -> anyhow::Result { + Ok(MptAccount { nonce: 1.into(), balance: 0.into(), storage_root: token_storage()?.hash(), @@ -280,8 +280,8 @@ fn token_account() -> anyhow::Result { }) } -fn sender_account() -> MptAccountRlp { - MptAccountRlp { +fn sender_account() -> MptAccount { + MptAccount { nonce: 0.into(), balance: sd2u("10000000000000000000000"), storage_root: Default::default(), diff --git a/evm_arithmetization/tests/erc20_type2.rs b/evm_arithmetization/tests/erc20_type2.rs index d21e05b3e..7f6ebe877 100644 --- a/evm_arithmetization/tests/erc20_type2.rs +++ b/evm_arithmetization/tests/erc20_type2.rs @@ -6,7 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{AccountRlp, LegacyReceiptRlp, LogRlp, SmtAccountRlp}; +use evm_arithmetization::generation::mpt::{Account, LegacyReceiptRlp, LogRlp, SmtAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -17,7 +17,7 @@ use evm_arithmetization::testing_utils::TIMESTAMP_STORAGE_POS; use evm_arithmetization::testing_utils::{init_logger, sd2u}; use evm_arithmetization::verifier::testing::verify_all_proofs; use evm_arithmetization::world::world::{StateWorld, Type2World}; -use evm_arithmetization::{AllStark, Node, EMPTY_CONSOLIDATED_BLOCKHASH}; +use evm_arithmetization::{AllStark, Node, StarkConfig, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; use mpt_trie::nibbles::Nibbles; @@ -132,7 +132,7 @@ fn test_erc20() -> anyhow::Result<()> { let expected_smt_after: StateWorld = { let mut smt = StateWorld::default(); let sender_account = sender_account(); - let sender_account_after = SmtAccountRlp { + let sender_account_after = SmtAccount { nonce: sender_account.nonce + 1, balance: sender_account.balance - gas_used * 0xa, ..sender_account @@ -310,10 +310,10 @@ fn scalable_storage_after(block: &BlockMetadata, state_root_before: U256) -> Has storage } -fn giver_account() -> SmtAccountRlp { +fn giver_account() -> SmtAccount { let code = giver_bytecode(); let len = code.len(); - SmtAccountRlp { + SmtAccount { nonce: 1.into(), balance: 0.into(), code_hash: hash_bytecode_u256(code), @@ -321,10 +321,10 @@ fn giver_account() -> SmtAccountRlp { } } -fn token_account() -> SmtAccountRlp { +fn token_account() -> SmtAccount { let code = token_bytecode(); let len = code.len(); - SmtAccountRlp { + SmtAccount { nonce: 1.into(), balance: 0.into(), code_hash: hash_bytecode_u256(code), @@ -332,16 +332,16 @@ fn token_account() -> SmtAccountRlp { } } -fn sender_account() -> SmtAccountRlp { - SmtAccountRlp { +fn sender_account() -> SmtAccount { + SmtAccount { nonce: 0.into(), balance: sd2u("10000000000000000000000"), ..Default::default() } } -fn scalable_account() -> SmtAccountRlp { - SmtAccountRlp { +fn scalable_account() -> SmtAccount { + SmtAccount { nonce: 0.into(), balance: 0.into(), ..Default::default() @@ -367,7 +367,7 @@ fn bloom() -> [U256; 8] { fn set_account( world: &mut StateWorld, addr: Address, - account: &SmtAccountRlp, + account: &SmtAccount, storage: &HashMap, code: &[u8], ) { diff --git a/evm_arithmetization/tests/erc721.rs b/evm_arithmetization/tests/erc721.rs index fffc1cd15..4afa1feb3 100644 --- a/evm_arithmetization/tests/erc721.rs +++ b/evm_arithmetization/tests/erc721.rs @@ -5,7 +5,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -137,13 +137,13 @@ fn test_erc721() -> anyhow::Result<()> { beacon_roots_contract_from_storage(&beacon_roots_account_storage); let owner_account = owner_account(); - let owner_account_after = MptAccountRlp { + let owner_account_after = MptAccount { nonce: owner_account.nonce + 1, balance: owner_account.balance - gas_used * 0xa, ..owner_account }; state_trie_after.insert(owner_nibbles, rlp::encode(&owner_account_after).to_vec())?; - let contract_account_after = MptAccountRlp { + let contract_account_after = MptAccount { storage_root: contract_storage_after()?.hash(), ..contract_account()? }; @@ -270,8 +270,8 @@ fn contract_storage_after() -> anyhow::Result { ]) } -fn owner_account() -> MptAccountRlp { - MptAccountRlp { +fn owner_account() -> MptAccount { + MptAccount { nonce: 2.into(), balance: 0x1000000.into(), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -279,8 +279,8 @@ fn owner_account() -> MptAccountRlp { } } -fn contract_account() -> anyhow::Result { - Ok(MptAccountRlp { +fn contract_account() -> anyhow::Result { + Ok(MptAccount { nonce: 0.into(), balance: 0.into(), storage_root: contract_storage()?.hash(), diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 41c5a4a8d..fd1d381c2 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -10,7 +10,7 @@ use ethereum_types::{Address, BigEndianHash, H256}; use evm_arithmetization::generation::mpt::transaction_testing::{ AddressOption, LegacyTransactionRlp, }; -use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, LogRlp, MptAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -70,20 +70,20 @@ fn test_log_opcodes() -> anyhow::Result<()> { let code_hash = keccak(code); // Set accounts before the transaction. - let beneficiary_account_before = MptAccountRlp { + let beneficiary_account_before = MptAccount { nonce: 1.into(), - ..MptAccountRlp::default() + ..MptAccount::default() }; let sender_balance_before = 5000000000000000u64; - let sender_account_before = MptAccountRlp { + let sender_account_before = MptAccount { balance: sender_balance_before.into(), - ..MptAccountRlp::default() + ..MptAccount::default() }; - let to_account_before = MptAccountRlp { + let to_account_before = MptAccount { balance: 9000000000u64.into(), code_hash, - ..MptAccountRlp::default() + ..MptAccount::default() }; // Initialize the state trie with three accounts. @@ -158,27 +158,27 @@ fn test_log_opcodes() -> anyhow::Result<()> { // Update the state and receipt tries after the transaction, so that we have the // correct expected tries: Update accounts #[cfg(feature = "cdk_erigon")] - let beneficiary_account_after = AccountRlp { + let beneficiary_account_after = Account { nonce: 1.into(), balance: block_metadata.block_base_fee * gas_used, - ..AccountRlp::default() + ..Account::default() }; #[cfg(feature = "eth_mainnet")] - let beneficiary_account_after = MptAccountRlp { + let beneficiary_account_after = MptAccount { nonce: 1.into(), - ..MptAccountRlp::default() + ..MptAccount::default() }; let sender_balance_after = sender_balance_before - gas_used * txn_gas_price; - let sender_account_after = MptAccountRlp { + let sender_account_after = MptAccount { balance: sender_balance_after.into(), nonce: 1.into(), - ..MptAccountRlp::default() + ..MptAccount::default() }; - let to_account_after = MptAccountRlp { + let to_account_after = MptAccount { balance: 9000000000u64.into(), code_hash, - ..MptAccountRlp::default() + ..MptAccount::default() }; update_beacon_roots_account_storage( diff --git a/evm_arithmetization/tests/selfdestruct.rs b/evm_arithmetization/tests/selfdestruct.rs index 8435aca90..04656b870 100644 --- a/evm_arithmetization/tests/selfdestruct.rs +++ b/evm_arithmetization/tests/selfdestruct.rs @@ -5,7 +5,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H256}; -use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -44,7 +44,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { 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 = MptAccountRlp { + let sender_account_before = MptAccount { nonce: 5.into(), balance: eth_to_wei(100_000.into()), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -54,7 +54,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { 0x32, // ORIGIN 0xFF, // SELFDESTRUCT ]; - let to_account_before = MptAccountRlp { + let to_account_before = MptAccount { nonce: 12.into(), balance: eth_to_wei(10_000.into()), storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -107,7 +107,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { let beacon_roots_account = beacon_roots_contract_from_storage(&beacon_roots_account_storage); - let sender_account_after = MptAccountRlp { + let sender_account_after = MptAccount { nonce: 6.into(), balance: eth_to_wei(110_000.into()) - 26_002 * 0xa, storage_root: HashedPartialTrie::from(Node::Empty).hash(), @@ -117,7 +117,7 @@ fn test_selfdestruct() -> anyhow::Result<()> { // EIP-6780: The account won't be deleted because it wasn't created during this // transaction. - let to_account_before = MptAccountRlp { + let to_account_before = MptAccount { nonce: 12.into(), balance: 0.into(), storage_root: HashedPartialTrie::from(Node::Empty).hash(), diff --git a/evm_arithmetization/tests/simple_transfer.rs b/evm_arithmetization/tests/simple_transfer.rs index a92fe3747..01b2f1693 100644 --- a/evm_arithmetization/tests/simple_transfer.rs +++ b/evm_arithmetization/tests/simple_transfer.rs @@ -6,7 +6,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{Address, BigEndianHash, H256, U256}; -use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -45,13 +45,13 @@ fn test_simple_transfer() -> anyhow::Result<()> { 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 = MptAccountRlp { + let sender_account_before = MptAccount { nonce: 5.into(), balance: eth_to_wei(100_000.into()), storage_root: HashedPartialTrie::from(Node::Empty).hash(), code_hash: keccak([]), }; - let to_account_before = MptAccountRlp::default(); + let to_account_before = MptAccount::default(); let (mut state_trie_before, storage_tries) = preinitialized_state_and_storage_tries()?; let mut beacon_roots_account_storage = storage_tries[0].1.clone(); @@ -101,12 +101,12 @@ fn test_simple_transfer() -> anyhow::Result<()> { log::debug!("beacon roots expected account:: {:?}", beacon_roots_account); - let sender_account_after = MptAccountRlp { + let sender_account_after = MptAccount { balance: sender_account_before.balance - value - gas_used * 10, nonce: sender_account_before.nonce + 1, ..sender_account_before }; - let to_account_after = MptAccountRlp { + let to_account_after = MptAccount { balance: value, ..to_account_before }; diff --git a/evm_arithmetization/tests/withdrawals.rs b/evm_arithmetization/tests/withdrawals.rs index cad90fe6c..00eacd78a 100644 --- a/evm_arithmetization/tests/withdrawals.rs +++ b/evm_arithmetization/tests/withdrawals.rs @@ -5,7 +5,7 @@ use std::time::Duration; use either::Either; use ethereum_types::{H160, H256, U256}; -use evm_arithmetization::generation::mpt::MptAccountRlp; +use evm_arithmetization::generation::mpt::MptAccount; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::prove_all_segments; @@ -61,9 +61,9 @@ fn test_withdrawals() -> anyhow::Result<()> { let addr_state_key = keccak(withdrawals[0].0); let addr_nibbles = Nibbles::from_bytes_be(addr_state_key.as_bytes()).unwrap(); - let account = MptAccountRlp { + let account = MptAccount { balance: withdrawals[0].1, - ..MptAccountRlp::default() + ..MptAccount::default() }; trie.insert(addr_nibbles, rlp::encode(&account).to_vec())?; trie.insert( diff --git a/mpt_trie/src/debug_tools/diff.rs b/mpt_trie/src/debug_tools/diff.rs index 6b0fb8c97..197c8c648 100644 --- a/mpt_trie/src/debug_tools/diff.rs +++ b/mpt_trie/src/debug_tools/diff.rs @@ -707,7 +707,7 @@ mod tests { #[derive( RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, )] - pub struct TestAccountRlp { + pub struct TestAccount { pub nonce: U256, pub balance: U256, pub storage_root: H256, @@ -717,7 +717,7 @@ mod tests { let mut data = vec![ ( keccak(hex::decode("f0d4c12a5768d806021f80a262b4d39d26c58b8d").unwrap()), - TestAccountRlp { + TestAccount { nonce: U256::from(1), balance: U256::from(2), storage_root: H256::from_uint(&1312378.into()), @@ -726,7 +726,7 @@ mod tests { ), ( keccak(hex::decode("95222290dd7278aa3ddd389cc1e1d165cc4bafe5").unwrap()), - TestAccountRlp { + TestAccount { nonce: U256::from(2), balance: U256::from(3), storage_root: H256::from_uint(&1123178.into()), @@ -735,7 +735,7 @@ mod tests { ), ( keccak(hex::decode("43682bcf1ce452a70b72c109551084076c6377e0").unwrap()), - TestAccountRlp { + TestAccount { nonce: U256::from(100), balance: U256::from(101), storage_root: H256::from_uint(&12345678.into()), @@ -744,7 +744,7 @@ mod tests { ), ( keccak(hex::decode("97a9a15168c22b3c137e6381037e1499c8ad0978").unwrap()), - TestAccountRlp { + TestAccount { nonce: U256::from(3000), balance: U256::from(3002), storage_root: H256::from_uint(&123456781.into()), @@ -753,7 +753,7 @@ mod tests { ), ]; - let create_trie_with_data = |trie: &Vec<(H256, TestAccountRlp)>| -> Result> { + let create_trie_with_data = |trie: &Vec<(H256, TestAccount)>| -> Result> { let mut tr = HashedPartialTrie::default(); tr.insert::(Nibbles::from_str(&hex::encode(trie[0].0.as_bytes()))?, rlp::encode(&trie[0].1).as_ref())?; tr.insert::(Nibbles::from_str(&hex::encode(trie[1].0.as_bytes()))?, rlp::encode(&trie[1].1).as_ref())?; diff --git a/trace_decoder/src/core.rs b/trace_decoder/src/core.rs index aa86c21af..754808225 100644 --- a/trace_decoder/src/core.rs +++ b/trace_decoder/src/core.rs @@ -201,7 +201,7 @@ fn start( path.into_hash() .context("invalid path length in direct state trie")?, rlp::decode(&bytes) - .context("invalid AccountRlp in direct state trie")?, + .context("invalid Account in direct state trie")?, )?; } mpt_trie::trie_ops::ValOrHash::Hash(h) => { diff --git a/zero/src/trie_diff/mod.rs b/zero/src/trie_diff/mod.rs index 8a5f7df3a..e89240d9f 100644 --- a/zero/src/trie_diff/mod.rs +++ b/zero/src/trie_diff/mod.rs @@ -1,4 +1,4 @@ -use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccountRlp}; +use evm_arithmetization::generation::mpt::{LegacyReceiptRlp, MptAccount}; use evm_arithmetization::generation::DebugOutputTries; use mpt_trie::debug_tools::diff::{create_full_diff_between_tries, DiffPoint}; use mpt_trie::utils::TrieNodeType; @@ -85,7 +85,7 @@ pub fn compare_tries( } let state_trie_diff = create_full_diff_between_tries(&left.state_trie, &right.state_trie); - compare_tries_and_output_results::( + compare_tries_and_output_results::( "state trie", state_trie_diff.diff_points, block_number, From 923943bb147ed2aaeaa8c3ccc527c6eab81ef6d0 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 7 Nov 2024 15:30:13 -0500 Subject: [PATCH 54/60] Renaming --- evm_arithmetization/src/cpu/kernel/asm/account_code.asm | 2 +- .../src/cpu/kernel/asm/core/create_contract_account.asm | 4 ++-- evm_arithmetization/src/cpu/kernel/asm/core/transfer.asm | 2 +- evm_arithmetization/src/cpu/kernel/asm/core/util.asm | 2 +- evm_arithmetization/src/cpu/kernel/asm/util/keccak.asm | 2 +- evm_arithmetization/src/cpu/kernel/constants/mod.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 17a9be1b1..426912653 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -57,7 +57,7 @@ global extcodehash: { %macro ext_code_empty %extcodehash - %eq_const(@EMPTY_STRING_HASH) + %eq_const(@EMPTY_STRING_KECCAK_HASH) %endmacro } #[cfg(feature = cdk_erigon)] diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm index f974952b5..b9ab42cdb 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create_contract_account.asm @@ -19,7 +19,7 @@ %add_const(3) // stack: existing_codehash_ptr, address DUP1 %mload_trie_data // codehash = account[3] - %eq_const(@EMPTY_STRING_HASH) ISZERO %jumpi(%%error_collision) + %eq_const(@EMPTY_STRING_KECCAK_HASH) ISZERO %jumpi(%%error_collision) // stack: existing_codehash_ptr, address %sub_const(2) %mload_trie_data // balance = account[1] %jump(%%do_insert) @@ -41,7 +41,7 @@ // stack: account_ptr, address PUSH 0 %append_to_trie_data // storage_root = nil // stack: account_ptr, address - PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') + PUSH @EMPTY_STRING_KECCAK_HASH %append_to_trie_data // code_hash = keccak('') // stack: account_ptr, address SWAP1 // stack: address, account_ptr diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/transfer.asm b/evm_arithmetization/src/cpu/kernel/asm/core/transfer.asm index b21828f5e..bca8ce988 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/transfer.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/transfer.asm @@ -98,7 +98,7 @@ global add_eth_new_account: %append_to_trie_data // balance // stack: addr, new_account_ptr, retdest PUSH 0 %append_to_trie_data // storage root pointer - PUSH @EMPTY_STRING_HASH %append_to_trie_data // code hash + PUSH @EMPTY_STRING_KECCAK_HASH %append_to_trie_data // code hash // stack: addr, new_account_ptr, retdest %addr_to_state_key // stack: key, new_account_ptr, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index 0e462cf40..a1a720b63 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -118,7 +118,7 @@ { %add_const(2) %mload_trie_data // stack: code_hash - PUSH @EMPTY_STRING_HASH + PUSH @EMPTY_STRING_KECCAK_HASH EQ } #[cfg(feature = cdk_erigon)] diff --git a/evm_arithmetization/src/cpu/kernel/asm/util/keccak.asm b/evm_arithmetization/src/cpu/kernel/asm/util/keccak.asm index dceb7b195..70fabb899 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/util/keccak.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/util/keccak.asm @@ -28,7 +28,7 @@ global sys_keccak256: sys_keccak256_empty: // stack: static_gas, kexit_info, offset, len %charge_gas - %stack (kexit_info, offset, len) -> (kexit_info, @EMPTY_STRING_HASH) + %stack (kexit_info, offset, len) -> (kexit_info, @EMPTY_STRING_KECCAK_HASH) EXIT_KERNEL // Computes Keccak256(input_word). Clobbers @SEGMENT_KERNEL_GENERAL. diff --git a/evm_arithmetization/src/cpu/kernel/constants/mod.rs b/evm_arithmetization/src/cpu/kernel/constants/mod.rs index 8e37d9543..4b4df6304 100644 --- a/evm_arithmetization/src/cpu/kernel/constants/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/constants/mod.rs @@ -185,7 +185,7 @@ const MISC_CONSTANTS: [(&str, [u8; 32]); 4] = [ const HASH_CONSTANTS: [(&str, [u8; 32]); 3] = [ // Hash of an empty string: keccak(b'').hex() ( - "EMPTY_STRING_HASH", + "EMPTY_STRING_KECCAK_HASH", hex!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), ), // Hash of an empty node: keccak(rlp.encode(b'')).hex() From 2009f66962702eae594f822004f70dcf07b98077 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 7 Nov 2024 15:42:51 -0500 Subject: [PATCH 55/60] Some more fixes --- .../benches/fibonacci_25m_gas.rs | 20 ++++------ evm_arithmetization/src/generation/mpt.rs | 32 +++------------ trace_decoder/src/core.rs | 15 +++---- trace_decoder/src/interface.rs | 8 ++-- trace_decoder/src/lib.rs | 39 +++++++++++++++++++ trace_decoder/src/type1.rs | 4 +- 6 files changed, 65 insertions(+), 53 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index a2bf1ee1c..226f4f019 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -15,13 +15,11 @@ use ethereum_types::H160; use ethereum_types::{Address, BigEndianHash, H256, U256}; use evm_arithmetization::cpu::kernel::aggregator::KERNEL; use evm_arithmetization::cpu::kernel::opcodes::{get_opcode, get_push_opcode}; -use evm_arithmetization::generation::mpt::{ - get_h256_from_code_hash, get_u256_from_code_hash, Account, CodeHashType, EitherAccount, - LegacyReceiptRlp, MptAccount, -}; +use evm_arithmetization::generation::mpt::{Account, EitherAccount, LegacyReceiptRlp, MptAccount}; use evm_arithmetization::generation::{GenerationInputs, TrieInputs}; use evm_arithmetization::proof::{BlockHashes, BlockMetadata, TrieRoots}; use evm_arithmetization::prover::testing::simulate_execution; +#[cfg(not(feature = "cdk_erigon"))] use evm_arithmetization::testing_utils::get_state_world; #[cfg(feature = "eth_mainnet")] use evm_arithmetization::testing_utils::{ @@ -88,9 +86,9 @@ fn prepare_setup() -> anyhow::Result> { ]; let code_hash = if cfg!(feature = "cdk_erigon") { - CodeHashType::Uint(hash_bytecode_h256(code.to_vec())) + hash_bytecode_h256(&code) } else { - CodeHashType::Hash(keccak(code)) + keccak(&code) }; let empty_trie_root = HashedPartialTrie::from(Node::Empty).hash(); @@ -99,7 +97,7 @@ fn prepare_setup() -> anyhow::Result> { Either::Right(SmtAccount { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, - code_hash: hash_bytecode_h256(&[]), + code_hash: hash_bytecode_h256(&[]).into_uint(), code_length: 0.into(), }) } else { @@ -115,8 +113,7 @@ fn prepare_setup() -> anyhow::Result> { EitherAccount(Either::Right(SmtAccount { nonce: 1.into(), balance: 0.into(), - code_hash: get_u256_from_code_hash(code_hash.clone()) - .expect("In cdk_erigon, the code_hash is a U256"), + code_hash: code_hash.into_uint(), code_length: code.len().into(), })) } else { @@ -124,8 +121,7 @@ fn prepare_setup() -> anyhow::Result> { nonce: 1.into(), balance: 0.into(), storage_root: empty_trie_root, - code_hash: get_h256_from_code_hash(code_hash.clone()) - .expect("In eth_mainnet, the code_hash is a H256"), + code_hash, })) }; @@ -353,7 +349,7 @@ fn set_account(world: &mut StateWorld, addr: Address, account: &SmtAccount, code if let Either::Right(ref mut smt_state) = world.state { smt_state.update_balance(addr, |b| *b = account.get_balance()); smt_state.update_nonce(addr, |n| *n = account.get_nonce()); - smt_state.set_code(addr, code); + smt_state.set_code(addr, Either::Left(code)); let key = key_code_length(addr); log::debug!( "setting {:?} code length, the key is {:?}", diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index e37c0ea84..9bf4b62fa 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -24,26 +24,6 @@ use crate::util::h2u; use crate::witness::errors::{ProgramError, ProverInputError}; use crate::Node; -#[derive(Clone)] -pub enum CodeHashType { - Hash(H256), - Uint(U256), -} - -pub fn get_h256_from_code_hash(code_hash: CodeHashType) -> Option { - match code_hash { - CodeHashType::Hash(h) => Some(h), - _ => None, - } -} - -pub fn get_u256_from_code_hash(code_hash: CodeHashType) -> Option { - match code_hash { - CodeHashType::Uint(u) => Some(u), - _ => None, - } -} - #[derive(RlpEncodable, RlpDecodable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct MptAccount { pub nonce: U256, @@ -65,8 +45,8 @@ impl Account for MptAccount { fn get_code_length(&self) -> U256 { panic!("No code length in an MPT's account.") } - fn get_code_hash(&self) -> CodeHashType { - CodeHashType::Hash(self.code_hash) + fn get_code_hash(&self) -> H256 { + self.code_hash } fn get_code_hash_u256(&self) -> U256 { self.code_hash.into_uint() @@ -97,8 +77,8 @@ impl Account for SmtAccount { fn get_code_length(&self) -> U256 { self.code_length } - fn get_code_hash(&self) -> CodeHashType { - CodeHashType::Uint(self.code_hash) + fn get_code_hash(&self) -> H256 { + H256::from_uint(&self.code_hash) } fn get_code_hash_u256(&self) -> U256 { self.code_hash @@ -113,7 +93,7 @@ pub trait Account: Any { fn get_balance(&self) -> U256; fn get_storage_root(&self) -> H256; fn get_code_length(&self) -> U256; - fn get_code_hash(&self) -> CodeHashType; + fn get_code_hash(&self) -> H256; fn get_code_hash_u256(&self) -> U256; fn rlp_encode(&self) -> BytesMut; } @@ -169,7 +149,7 @@ impl Account for EitherAccount { Either::Right(smt_rlp) => smt_rlp.get_code_length(), } } - fn get_code_hash(&self) -> CodeHashType { + fn get_code_hash(&self) -> H256 { match self.0 { Either::Left(mpt_rlp) => mpt_rlp.get_code_hash(), Either::Right(smt_rlp) => smt_rlp.get_code_hash(), diff --git a/trace_decoder/src/core.rs b/trace_decoder/src/core.rs index a3e617781..d263c47b2 100644 --- a/trace_decoder/src/core.rs +++ b/trace_decoder/src/core.rs @@ -12,14 +12,13 @@ use evm_arithmetization::{ generation::TrieInputs, proof::{BlockMetadata, TrieRoots}, tries::{MptKey, ReceiptTrie, StateMpt, StorageTrie, TransactionTrie}, - world::{Hasher, KeccakHash, PoseidonHash, Type1World, Type2World, World}, + world::{Hasher, KeccakHash, PoseidonHash, StateWorld, Type1World, Type2World, World}, GenerationInputs, }; use itertools::Itertools as _; use keccak_hash::H256; use mpt_trie::partial_trie::PartialTrie as _; use nunny::NonEmpty; -use smt_trie::code::hash_bytecode_h256; use zk_evm_common::gwei_to_wei; use crate::observer::{DummyObserver, Observer}; @@ -134,10 +133,6 @@ pub fn entrypoint( after, withdrawals, }| { - let (state, storage) = world - .clone() - .expect_left("TODO(0xaatif): evm_arithemetization accepts an SMT") - .into_state_and_storage(); GenerationInputs { txn_number_before: first_txn_ix.into(), gas_used_before: running_gas_used.into(), @@ -149,7 +144,9 @@ pub fn entrypoint( withdrawals, ger_data, tries: TrieInputs { - state_trie: StateWorld { state: world }, + state_trie: StateWorld { + state: world.clone(), + }, transactions_trie: transaction.into(), receipts_trie: receipt.into(), }, @@ -238,11 +235,11 @@ fn start( Either::Left((Type1World::new(state, storage)?, Hash2Code::new())) } BlockTraceTriePreImages::Combined(CombinedPreImages { compact }) => { - let instructions = evm_arithmetization::world::wire::parse(&compact) + let instructions = crate::wire::parse(&compact) .context("couldn't parse instructions from binary format")?; match wire_disposition { WireDisposition::Type1 => { - let type1::Frontend { + let crate::type1::Frontend { state, storage, code, diff --git a/trace_decoder/src/interface.rs b/trace_decoder/src/interface.rs index 75c91c52f..abe3b0af0 100644 --- a/trace_decoder/src/interface.rs +++ b/trace_decoder/src/interface.rs @@ -67,7 +67,7 @@ pub enum SeparateTriePreImage { #[serde(rename_all = "snake_case")] pub struct CombinedPreImages { /// Compact combined state and storage tries. - #[serde(with = "evm_arithmetization::world::hex")] + #[serde(with = "crate::hex")] pub compact: Vec, } @@ -100,13 +100,13 @@ pub struct TxnMeta { /// Txn byte code. This is also the raw RLP bytestring inserted into the txn /// trie by this txn. Note that the key is not included and this is only /// the rlped value of the node! - #[serde(with = "evm_arithmetization::world::hex")] + #[serde(with = "crate::hex")] pub byte_code: Vec, /// Rlped bytes of the new receipt value inserted into the receipt trie by /// this txn. Note that the key is not included and this is only the rlped /// value of the node! - #[serde(with = "evm_arithmetization::world::hex")] + #[serde(with = "crate::hex")] pub new_receipt_trie_node_byte: Vec, /// Gas used by this txn (Note: not cumulative gas used). @@ -160,7 +160,7 @@ pub enum ContractCodeUsage { /// Contract was created (and these are the bytes). Note that this new /// contract code will not appear in the [`BlockTrace`] map. - Write(#[serde(with = "evm_arithmetization::world::hex")] Vec), + Write(#[serde(with = "crate::hex")] Vec), } /// Other data that is needed for proof gen. diff --git a/trace_decoder/src/lib.rs b/trace_decoder/src/lib.rs index 87bc83f91..160d48470 100644 --- a/trace_decoder/src/lib.rs +++ b/trace_decoder/src/lib.rs @@ -72,3 +72,42 @@ pub use core::{entrypoint, WireDisposition}; /// Implementation of the observer for the trace decoder. pub mod observer; +/// Like `#[serde(with = "hex")`, but tolerates and emits leading `0x` prefixes +mod hex { + use serde::{de::Error as _, Deserialize as _, Deserializer, Serializer}; + + pub fn serialize(data: T, serializer: S) -> Result + where + T: hex::ToHex, + { + let s = data.encode_hex::(); + serializer.serialize_str(&format!("0x{}", s)) + } + + pub fn deserialize<'de, D: Deserializer<'de>, T>(deserializer: D) -> Result + where + T: hex::FromHex, + T::Error: std::fmt::Display, + { + let s = String::deserialize(deserializer)?; + match s.strip_prefix("0x") { + Some(rest) => T::from_hex(rest), + None => T::from_hex(&*s), + } + .map_err(D::Error::custom) + } +} + +#[cfg(test)] +#[derive(serde::Deserialize)] +struct Case { + #[serde(with = "hex")] + pub bytes: Vec, + #[serde(deserialize_with = "h256")] + pub expected_state_root: ethereum_types::H256, +} + +#[cfg(test)] +fn h256<'de, D: serde::Deserializer<'de>>(it: D) -> Result { + Ok(ethereum_types::H256(hex::deserialize(it)?)) +} diff --git a/trace_decoder/src/type1.rs b/trace_decoder/src/type1.rs index 2d9e293d5..20d71586e 100644 --- a/trace_decoder/src/type1.rs +++ b/trace_decoder/src/type1.rs @@ -6,7 +6,7 @@ use std::collections::{BTreeMap, BTreeSet}; use anyhow::{bail, ensure, Context as _}; use either::Either; -use evm_arithmetization::generation::mpt::AccountRlp; +use evm_arithmetization::generation::mpt::MptAccount; use evm_arithmetization::tries::{MptKey, StateMpt, StorageTrie}; use evm_arithmetization::world::{Hasher as _, Type1World, World}; use keccak_hash::H256; @@ -69,7 +69,7 @@ fn visit( storage, code, }) => { - let account = AccountRlp { + let account = MptAccount { nonce: nonce.into(), balance, storage_root: { From 2cc321ac16d47db63a02cab4decb3d2e5761614c Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Fri, 8 Nov 2024 14:22:20 +0100 Subject: [PATCH 56/60] Fix more unit tests --- .../src/cpu/kernel/tests/account_code.rs | 3 +- .../src/cpu/kernel/tests/mpt/hash.rs | 11 +++- .../src/cpu/kernel/tests/mpt/linked_list.rs | 63 +++++++++++-------- .../src/cpu/kernel/tests/mpt/load.rs | 9 ++- .../src/cpu/kernel/tests/mpt/mod.rs | 5 +- .../src/cpu/kernel/tests/mpt/read.rs | 10 ++- .../src/cpu/kernel/tests/transient_storage.rs | 6 ++ .../src/generation/prover_input.rs | 4 +- evm_arithmetization/src/testing_utils.rs | 5 -- 9 files changed, 72 insertions(+), 44 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index ea58107a1..ceea2441d 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -530,8 +530,7 @@ fn sstore() -> Result<()> { let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert(addr_nibbles, account_before.rlp_encode().to_vec())?; - let state_trie = get_state_world(state_trie_before, vec![(addr_hashed, HashedPartialTrie::from(Node::Empty))]);// storage tries is empty but should contain empty tries? - + let state_trie = get_state_world(state_trie_before, vec![(addr_hashed, HashedPartialTrie::from(Node::Empty))]); let trie_inputs = TrieInputs { state_trie, transactions_trie: Node::Empty.into(), diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs index f5a16803b..3a9670b73 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/hash.rs @@ -1,5 +1,6 @@ use anyhow::Result; use ethereum_types::{BigEndianHash, H256}; +use mpt_trie::nibbles::Nibbles; use plonky2::field::goldilocks_field::GoldilocksField as F; use crate::cpu::kernel::aggregator::KERNEL; @@ -62,7 +63,10 @@ fn mpt_hash_hash() -> Result<()> { fn mpt_hash_leaf() -> Result<()> { let state_trie = get_state_world( Node::Leaf { - nibbles: 0xABC_u64.into(), + nibbles: Nibbles{ + count: 64, + packed: 0xABC_u64.into(), + }, value: test_account_1_rlp(), } .into(), @@ -90,7 +94,10 @@ fn mpt_hash_extension_to_leaf() -> Result<()> { #[test] fn mpt_hash_branch_to_leaf() -> Result<()> { let leaf = Node::Leaf { - nibbles: 0xABC_u64.into(), + nibbles: Nibbles { + count: 63, + packed: 0xABC_u64.into(), + }, value: test_account_2_rlp(), } .into(); 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 076e9432e..7ea7355aa 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/linked_list.rs @@ -124,17 +124,16 @@ fn test_list_iterator() -> Result<()> { let Some([addr, _key, ptr, ptr_cpy, scaled_pos_1]) = storage_list.next() else { return Err(anyhow::Error::msg("Couldn't get value")); }; + assert_eq!(addr, U256::MAX); + assert_eq!(ptr, U256::zero()); + assert_eq!(ptr_cpy, U256::zero()); + assert_eq!(scaled_pos_1, (Segment::StorageLinkedList as usize).into()); + assert_eq!(addr, U256::MAX); + assert_eq!(ptr, U256::zero()); + assert_eq!(ptr_cpy, U256::zero()); + assert_eq!(scaled_pos_1, (Segment::StorageLinkedList as usize).into()); } - assert_eq!(addr, U256::MAX); - assert_eq!(ptr, U256::zero()); - assert_eq!(ptr_cpy, U256::zero()); - assert_eq!(scaled_pos_1, (Segment::StorageLinkedList as usize).into()); - assert_eq!(addr, U256::MAX); - assert_eq!(ptr, U256::zero()); - assert_eq!(ptr_cpy, U256::zero()); - assert_eq!(scaled_pos_1, (Segment::StorageLinkedList as usize).into()); - Ok(()) } @@ -244,7 +243,7 @@ fn test_insert_storage() -> Result<()> { (Segment::StorageLinkedList as usize + init_len).into(), ); - let insert_account_label = KERNEL.global_labels["insert_slot"]; + let insert_slot_label = KERNEL.global_labels["insert_slot"]; let retaddr = 0xdeadbeefu32.into(); let mut rng = thread_rng(); @@ -266,10 +265,10 @@ fn test_insert_storage() -> Result<()> { interpreter .push(U256::from(address.0.as_slice())) .expect("The stack should not overflow"); - interpreter.generation_state.registers.program_counter = insert_account_label; + interpreter.generation_state.registers.program_counter = insert_slot_label; interpreter.run()?; - assert_eq!(interpreter.stack(), &[payload_ptr]); + assert_eq!(interpreter.stack(), &[]); let accounts_mem = interpreter .generation_state @@ -278,6 +277,8 @@ fn test_insert_storage() -> Result<()> { let mut list = StorageLinkedList::from_mem_and_segment(&accounts_mem, Segment::StorageLinkedList).unwrap(); + log::debug!("ll = {:?}", list); + let Some([inserted_addr, inserted_key, ptr, ptr_cpy, _]) = list.next() else { return Err(anyhow::Error::msg("Couldn't get value")); }; @@ -293,7 +294,7 @@ fn test_insert_storage() -> Result<()> { assert_eq!(inserted_addr, U256::from(address.0.as_slice())); assert_eq!(inserted_key, U256::from(key.0.as_slice())); assert_eq!(ptr, payload_ptr); - assert_eq!(ptr_cpy, U256::zero()); // ptr_cpy is zero because the trie data segment is empty + assert_eq!(ptr_cpy, payload_ptr); assert_eq!( scaled_next_pos, (Segment::StorageLinkedList as usize).into() @@ -531,8 +532,6 @@ fn test_insert_and_delete_storage() -> Result<()> { H160::from_low_u64_be(i as u64 + 6), ] }) - .collect::>() - .into_iter() .collect::>(); let delta_ptr = 100; let addr_not_in_list = Address::from_low_u64_be(4); @@ -560,16 +559,28 @@ fn test_insert_and_delete_storage() -> Result<()> { .expect("The stack should not overflow"); interpreter.generation_state.registers.program_counter = insert_slot_label; interpreter.run()?; + assert_eq!(interpreter.stack(), &[]); + + let mem = interpreter + .generation_state + .memory + .get_preinit_memory(Segment::StorageLinkedList); + log::debug!( + "for i = {i} storage linked list = {:?}", + StorageLinkedList::from_mem_and_segment(&mem, Segment::StorageLinkedList) + ); + assert_eq!( - interpreter.pop().expect("The stack can't be empty"), - addr + delta_ptr + interpreter.generation_state.memory.get_with_init( + MemoryAddress::new_bundle(U256::from(offset + 5 * (i + 1) + 2)).unwrap(), + ), + (addr + delta_ptr).into() ); - // The ptr_cpy must be 0 assert_eq!( interpreter.generation_state.memory.get_with_init( MemoryAddress::new_bundle(U256::from(offset + 5 * (i + 1) + 3)).unwrap(), ), - i.into() + (addr + delta_ptr).into() ); } @@ -603,15 +614,18 @@ fn test_insert_and_delete_storage() -> Result<()> { interpreter.generation_state.registers.program_counter = insert_slot_label; interpreter.run()?; + assert_eq!(interpreter.stack(), &[]); assert_eq!( - interpreter.pop().expect("The stack can't be empty"), - addr_in_list + delta_ptr + interpreter.generation_state.memory.get_with_init( + MemoryAddress::new_bundle(U256::from(offset + 5 * (i + 1) + 2)).unwrap(), + ), + (addr_in_list + delta_ptr).into() ); assert_eq!( interpreter.generation_state.memory.get_with_init( MemoryAddress::new_bundle(U256::from(offset + 5 * (i + 1) + 3)).unwrap(), ), - i.into() + (addr_in_list + delta_ptr).into() ); } @@ -632,10 +646,7 @@ fn test_insert_and_delete_storage() -> Result<()> { interpreter.run()?; - assert_eq!( - interpreter.pop().expect("The stack can't be empty"), - U256::from(addr_not_in_list.0.as_slice()) + delta_ptr - ); + assert_eq!(interpreter.stack(), &[]); // Now the list of accounts have [4, 5] addresses_and_keys.push([addr_not_in_list, key_not_in_list]); diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs index be0b3f2a2..8f84efba9 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/load.rs @@ -56,7 +56,10 @@ fn load_all_mpts_empty() -> Result<()> { fn load_all_mpts_leaf() -> Result<()> { let state_trie = get_state_world( Node::Leaf { - nibbles: 0xABC_u64.into(), + nibbles: Nibbles { + count: 64, + packed: 0xABC_u64.into(), + }, value: test_account_1_rlp(), } .into(), @@ -246,11 +249,11 @@ fn load_all_mpts_ext_to_leaf() -> Result<()> { test_account_1().code_hash.into_uint(), // Values used for hashing. type_extension, - 64.into(), // should be 3 nibbles but keys are extended for `Type1World` + 61.into(), // The extension node has 61 nibbles 0xABC.into(), // key part 9.into(), // Pointer to the leaf node immediately below. type_leaf, - 64.into(), // should be 3 nibbles but keys are extended for `Type1World` + 3.into(), // The remaining 3 nibbles 0xDEF.into(), // key part 13.into(), // value pointer test_account_1().nonce, diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs index cbe19a8b4..dd9502f89 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/mod.rs @@ -98,7 +98,10 @@ pub(crate) fn test_account_2_rlp() -> Vec { /// account. pub(crate) fn extension_to_leaf(value: Vec) -> HashedPartialTrie { Node::Extension { - nibbles: 0xABC_u64.into(), + nibbles: Nibbles { + count: 61, + packed: 0xABC_u64.into(), + }, child: Node::Leaf { nibbles: Nibbles { count: 3, diff --git a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs index 6e617f0a7..6e1a87567 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/mpt/read.rs @@ -8,16 +8,19 @@ use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::account_code::initialize_mpts; use crate::cpu::kernel::tests::mpt::{extension_to_leaf, test_account_1, test_account_1_rlp}; use crate::generation::TrieInputs; -use crate::testing_utils::get_state_world; +use crate::testing_utils::{get_state_world, init_logger}; #[test] fn mpt_read() -> Result<()> { + init_logger(); let trie_inputs = TrieInputs { state_trie: get_state_world(extension_to_leaf(test_account_1_rlp()), vec![]), transactions_trie: Default::default(), receipts_trie: Default::default(), }; + log::debug!("state trie: {:?}", trie_inputs.state_trie); + let mpt_read = KERNEL.global_labels["mpt_read"]; let initial_stack = vec![]; @@ -34,7 +37,7 @@ fn mpt_read() -> Result<()> { .push(0xABCDEFu64.into()) .expect("The stack should not overflow"); interpreter - .push(6.into()) + .push(64.into()) .expect("The stack should not overflow"); interpreter .push(interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot)) @@ -42,8 +45,9 @@ fn mpt_read() -> Result<()> { interpreter.run()?; assert_eq!(interpreter.stack().len(), 1); - // mpt_read returns a pointer to the accounts pointer + // mpt_read returns a pointer to a pointer to the accounts pointer let result_ptr_ptr = interpreter.stack()[0].as_usize(); + log::debug!("el ptr = {result_ptr_ptr}"); let result_ptr = interpreter.get_trie_data()[result_ptr_ptr..][..4][0].as_usize(); let result = &interpreter.get_trie_data()[result_ptr..][..4]; assert_eq!(result[0], test_account_1().nonce); diff --git a/evm_arithmetization/src/cpu/kernel/tests/transient_storage.rs b/evm_arithmetization/src/cpu/kernel/tests/transient_storage.rs index e874b9ca6..f8b644adb 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/transient_storage.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/transient_storage.rs @@ -13,6 +13,7 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::generation::state::GenerationState; use crate::memory::segments::Segment; +use crate::testing_utils::init_logger; use crate::witness::memory::MemoryAddress; use crate::GenerationInputs; @@ -220,6 +221,7 @@ fn test_many_tstore_many_tload() -> Result<()> { #[test] fn test_revert() -> Result<()> { + init_logger(); // We use a modified kernel with an extra file defining a label // where the `checkpoint` macro from file cpu/kernel/asm/journal/journal.asm // is expanded. @@ -268,6 +270,8 @@ fn test_revert() -> Result<()> { let gas_before_checkpoint = interpreter.generation_state.registers.gas_used; + log::debug!("Saperlipopete"); + // We will revert to the point where `val` was 9 let checkpoint = TEST_KERNEL.global_labels["checkpoint"]; interpreter.generation_state.registers.program_counter = checkpoint; @@ -323,6 +327,8 @@ fn test_revert() -> Result<()> { .push(kexit_info) .expect("The stack should not overflow"); assert!(interpreter.run().is_err()); + + log::debug!("Yubigobinabi"); // Now we should load the value before the revert let sys_tload = TEST_KERNEL.global_labels["sys_tload"]; diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index 8d278cd49..9540cf179 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -941,7 +941,7 @@ impl GenerationState { self.get_code(self.registers.context) } - fn get_code(&self, context: usize) -> Result, ProgramError> { + pub(crate) fn get_code(&self, context: usize) -> Result, ProgramError> { let code_len = self.get_code_len(context)?; let code = (0..code_len) .map(|i| { @@ -954,7 +954,7 @@ impl GenerationState { Ok(code) } - fn get_code_len(&self, context: usize) -> Result { + pub fn get_code_len(&self, context: usize) -> Result { let code_len = u256_to_usize(self.memory.get_with_init(MemoryAddress::new( context, Segment::ContextMetadata, diff --git a/evm_arithmetization/src/testing_utils.rs b/evm_arithmetization/src/testing_utils.rs index b2ce97146..0aac863e6 100644 --- a/evm_arithmetization/src/testing_utils.rs +++ b/evm_arithmetization/src/testing_utils.rs @@ -307,11 +307,6 @@ pub fn get_state_world( tries::{StateMpt, StorageTrie}, world::Type1World, }; - let state = HashedPartialTrie::try_from_iter(state.items().map(|(mut key, val)| { - key.count = 64; - (key, val) - })) - .expect("This should never fail"); let mut type1world = Type1World::new(StateMpt::new_with_inner(state), BTreeMap::default()).unwrap(); From da3dc9dbfcda791291b20111af3a2ca709cfe230 Mon Sep 17 00:00:00 2001 From: Alonso Gonzalez Date: Fri, 8 Nov 2024 17:22:43 +0100 Subject: [PATCH 57/60] Fix all unit tests --- .../src/cpu/kernel/asm/main.asm | 2 + .../src/cpu/kernel/tests/account_code.rs | 44 +++++++++++++------ evm_arithmetization/src/generation/mpt.rs | 29 ++---------- evm_arithmetization/src/generation/state.rs | 22 ++++++---- evm_arithmetization/src/witness/transition.rs | 9 ++-- trace_decoder/tests/simulate-execution.rs | 18 +++++--- 6 files changed, 65 insertions(+), 59 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index dc0c145f4..2f4c5013e 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -117,6 +117,7 @@ global hash_initial_tries: // The trie data segment contains only the empty node PUSH 2 } + global debug_init_trie_data_len: // stack: init_trie_data_len PUSH @INITIAL_RLP_ADDR // stack: rlp_start, init_trie_data_len @@ -127,6 +128,7 @@ global hash_initial_tries: // stack: trie_data_full_len // Check that the trie data length is correct. %mload_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE) +global debug_asdasdasd: %assert_eq global start_txns: diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 12001910e..7abb89e5c 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -20,8 +20,11 @@ use crate::cpu::kernel::constants::INITIAL_RLP_ADDR; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; #[cfg(not(feature = "cdk_erigon"))] -use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; -use crate::generation::mpt::{load_state_mpt, Account, EitherAccount, MptAccount, SmtAccount}; +use crate::generation::mpt::load_linked_lists; +use crate::generation::mpt::{ + load_receipts_mpt, load_state_mpt, load_transactions_mpt, Account, EitherAccount, MptAccount, + SmtAccount, TrieRootPtrs, +}; use crate::generation::TrieInputs; use crate::memory::segments::Segment; use crate::util::h2u; @@ -43,16 +46,28 @@ pub(crate) fn initialize_mpts( // Load all MPTs. #[cfg(not(feature = "cdk_erigon"))] { - let (mut trie_root_ptrs, state_leaves, storage_leaves, trie_data) = - load_linked_lists_and_txn_and_receipt_mpts( - &mut interpreter - .generation_state - .state_pointers - .accounts_pointers, - &mut interpreter.generation_state.state_pointers.storage_pointers, - trie_inputs, - ) - .expect("Invalid MPT data for preinitialization"); + let (state_leaves, storage_leaves, mut trie_data) = load_linked_lists( + &mut interpreter + .generation_state + .state_pointers + .accounts_pointers, + &mut interpreter.generation_state.state_pointers.storage_pointers, + trie_inputs, + ) + .expect("Invalid MPT data for preinitialization"); + + let txn_root_ptr = + load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); + let receipt_root_ptr = + load_receipts_mpt(&trie_inputs.receipts_trie, &mut trie_data).unwrap(); + + let mut trie_root_ptrs = TrieRootPtrs { + state_root_ptr: None, + txn_root_ptr, + receipt_root_ptr, + }; + + log::debug!("trie data len after receipts {:?}", trie_data.len()); interpreter.generation_state.memory.contexts[0].segments [Segment::AccountsLinkedList.unscale()] @@ -518,7 +533,10 @@ fn sstore() -> Result<()> { let mut state_trie_before = HashedPartialTrie::from(Node::Empty); state_trie_before.insert(addr_nibbles, account_before.rlp_encode().to_vec())?; - let state_trie = get_state_world(state_trie_before, vec![(addr_hashed, HashedPartialTrie::from(Node::Empty))]); + let state_trie = get_state_world( + state_trie_before, + vec![(addr_hashed, HashedPartialTrie::from(Node::Empty))], + ); let trie_inputs = TrieInputs { state_trie, transactions_trie: Node::Empty.into(), diff --git a/evm_arithmetization/src/generation/mpt.rs b/evm_arithmetization/src/generation/mpt.rs index 46f80ab86..e8ad14ef1 100644 --- a/evm_arithmetization/src/generation/mpt.rs +++ b/evm_arithmetization/src/generation/mpt.rs @@ -510,6 +510,7 @@ fn get_state_and_storage_leaves( storage_pointers: &mut BTreeMap<(U256, U256), usize>, storage_tries_by_state_key: &HashMap, ) -> Result<(), ProgramError> { + log::debug!("lee su trie data len a {:?}", trie_data.len()); match trie.deref() { Node::Branch { children, value } => { if !value.is_empty() { @@ -709,15 +710,10 @@ where /// - the vector of state trie leaves /// - the vector of storage trie leaves /// - the `TrieData` segment's memory content -type LinkedListsAndTrieData = ( - TrieRootPtrs, - Vec>, - Vec>, - Vec>, -); +type LinkedListsAndTrieData = (Vec>, Vec>, Vec>); #[cfg(not(feature = "cdk_erigon"))] -pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( +pub(crate) fn load_linked_lists( accounts_pointers: &mut BTreeMap, storage_pointers: &mut BTreeMap<(U256, U256), usize>, trie_inputs: &TrieInputs, @@ -743,14 +739,6 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( }) .collect(); - let txn_root_ptr = load_mpt(&trie_inputs.transactions_trie, &mut trie_data, &|rlp| { - let mut parsed_txn = vec![U256::from(rlp.len())]; - parsed_txn.extend(rlp.iter().copied().map(U256::from)); - Ok(parsed_txn) - })?; - - let receipt_root_ptr = load_mpt(&trie_inputs.receipts_trie, &mut trie_data, &parse_receipts)?; - get_state_and_storage_leaves( &mpt_state.state_trie(), empty_nibbles(), @@ -762,16 +750,7 @@ pub(crate) fn load_linked_lists_and_txn_and_receipt_mpts( &storage_tries_by_state_key, )?; - Ok(( - TrieRootPtrs { - state_root_ptr: None, - txn_root_ptr, - receipt_root_ptr, - }, - state_leaves, - storage_leaves, - trie_data, - )) + Ok((state_leaves, storage_leaves, trie_data)) } pub(crate) fn load_state_mpt( diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index ba0472413..36c4e3d6c 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -20,7 +20,7 @@ use crate::cpu::stack::MAX_USER_STACK_SIZE; use crate::generation::linked_list::{empty_list_mem, STATE_LINKED_LIST_NODE_SIZE}; use crate::generation::linked_list::{AccessLinkedListsPtrs, StateLinkedListsPtrs}; #[cfg(not(feature = "cdk_erigon"))] -use crate::generation::mpt::load_linked_lists_and_txn_and_receipt_mpts; +use crate::generation::mpt::load_linked_lists; use crate::generation::mpt::{load_receipts_mpt, load_transactions_mpt}; use crate::generation::rlp::all_rlp_prover_inputs_reversed; use crate::generation::CpuColumnsView; @@ -224,9 +224,9 @@ pub(crate) trait State { { use crate::cpu::kernel::tests::mpt::linked_list::StorageLinkedList; let mem = self - .get_generation_state() - .memory - .get_preinit_memory(Segment::StorageLinkedList); + .get_generation_state() + .memory + .get_preinit_memory(Segment::StorageLinkedList); log::debug!( "initial storage linked list = {:?}", StorageLinkedList::from_mem_and_segment(&mem, Segment::StorageLinkedList) @@ -362,13 +362,13 @@ pub(crate) trait State { /// Logs `msg` in `debug` mode. #[inline] fn log_debug(&self, msg: String) { - // log::debug!("{}", msg); + log::debug!("{}", msg); } /// Logs `msg` at `level`. #[inline] fn log(&self, level: Level, msg: String) { - // log::log!(level, "{}", msg); + log::log!(level, "{}", msg); } } @@ -432,10 +432,16 @@ impl GenerationState { let mut trie_data = self.memory.get_preinit_memory(Segment::TrieData); + log::debug!("trie data len after ll {:?}", trie_data.len()); + let txn_root_ptr = load_transactions_mpt(&trie_inputs.transactions_trie, &mut trie_data).unwrap(); + + log::debug!("trie data len after txn {:?}", trie_data.len()); let receipt_root_ptr = load_receipts_mpt(&trie_inputs.receipts_trie, &mut trie_data).unwrap(); + + log::debug!("trie data len after receipts {:?}", trie_data.len()); self.memory.insert_preinitialized_segment( Segment::TrieData, crate::witness::memory::MemorySegmentState { content: trie_data }, @@ -450,8 +456,8 @@ impl GenerationState { #[cfg(not(feature = "cdk_erigon"))] fn preinitialize_linked_lists(&mut self, trie_inputs: &TrieInputs) { let generation_state = self.get_mut_generation_state(); - let (_trie_root_ptrs, state_leaves, storage_leaves, trie_data) = - load_linked_lists_and_txn_and_receipt_mpts( + let (state_leaves, storage_leaves, trie_data) = + load_linked_lists( &mut generation_state.state_pointers.accounts_pointers, &mut generation_state.state_pointers.storage_pointers, trie_inputs, diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 3a1ecd2f7..30632b860 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -401,12 +401,9 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ); } - assert!( - pc < KERNEL.code.len(), - "Kernel PC is out of range: {} while KERNEL len is {}", - pc, - KERNEL.code.len() - ); + let kernel_code = + &state.get_generation_state().memory.contexts[0].segments[Segment::Code.unscale()].content; + assert!(pc < kernel_code.len(), "Kernel PC is out of range: {}", pc); } pub(crate) trait Transition: State diff --git a/trace_decoder/tests/simulate-execution.rs b/trace_decoder/tests/simulate-execution.rs index fc7136c34..79613c45c 100644 --- a/trace_decoder/tests/simulate-execution.rs +++ b/trace_decoder/tests/simulate-execution.rs @@ -6,12 +6,14 @@ mod common; use anyhow::Context as _; use common::{cases, Case}; +use evm_arithmetization::testing_utils::init_logger; use libtest_mimic::{Arguments, Trial}; use plonky2::field::goldilocks_field::GoldilocksField; use trace_decoder::observer::DummyObserver; use zero::prover::WIRE_DISPOSITION; fn main() -> anyhow::Result<()> { + init_logger(); let mut trials = vec![]; for batch_size in [1, 3] { for Case { @@ -32,16 +34,18 @@ fn main() -> anyhow::Result<()> { "error in `trace_decoder` for {name} at batch size {batch_size}" ))?; for (ix, gi) in gen_inputs.into_iter().enumerate() { - trials.push(Trial::test( - format!("{name}@{batch_size}/{ix}"), - move || { - evm_arithmetization::prover::testing::simulate_execution_all_segments::< + if name == "b2841_dev" && batch_size == 1 && ix == 0 { + trials.push(Trial::test( + format!("{name}@{batch_size}/{ix}"), + move || { + evm_arithmetization::prover::testing::simulate_execution_all_segments::< GoldilocksField, >(gi, 19) .map_err(|e| format!("{e:?}"))?; // get the full error chain - Ok(()) - }, - )) + Ok(()) + }, + )) + } } } } From ce0f872886a885e3219a930265778e045b962a3d Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Fri, 8 Nov 2024 11:25:53 -0500 Subject: [PATCH 58/60] Implement World for StateWorld --- .../benches/fibonacci_25m_gas.rs | 6 +- evm_arithmetization/src/world.rs | 128 ++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/evm_arithmetization/benches/fibonacci_25m_gas.rs b/evm_arithmetization/benches/fibonacci_25m_gas.rs index 226f4f019..360e54344 100644 --- a/evm_arithmetization/benches/fibonacci_25m_gas.rs +++ b/evm_arithmetization/benches/fibonacci_25m_gas.rs @@ -26,7 +26,7 @@ use evm_arithmetization::testing_utils::{ beacon_roots_account_nibbles, beacon_roots_contract_from_storage, preinitialized_state_and_storage_tries, update_beacon_roots_account_storage, }; -use evm_arithmetization::world::StateWorld; +use evm_arithmetization::world::{StateWorld, World}; use evm_arithmetization::{Node, EMPTY_CONSOLIDATED_BLOCKHASH}; use hex_literal::hex; use keccak_hash::keccak; @@ -65,6 +65,8 @@ fn criterion_benchmark(c: &mut Criterion) { } fn prepare_setup() -> anyhow::Result> { + let state_world = StateWorld::default(); + let sender = hex!("8943545177806ED17B9F23F0a21ee5948eCaa776"); let to = hex!("159271B89fea49aF29DFaf8b4eCE7D042D5d6f07"); @@ -97,7 +99,7 @@ fn prepare_setup() -> anyhow::Result> { Either::Right(SmtAccount { nonce: 169.into(), balance: U256::from_dec_str("999999999998417410153631615")?, - code_hash: hash_bytecode_h256(&[]).into_uint(), + code_hash: state_world.hash_code(&[]).into_uint(), code_length: 0.into(), }) } else { diff --git a/evm_arithmetization/src/world.rs b/evm_arithmetization/src/world.rs index 3d2863c7b..79e066f6a 100644 --- a/evm_arithmetization/src/world.rs +++ b/evm_arithmetization/src/world.rs @@ -84,6 +84,11 @@ pub trait World { /// Creates a new account at `address` if it does not exist. fn update_nonce(&mut self, address: Address, f: impl FnOnce(&mut U256)) -> anyhow::Result<()>; + /// Hash the provided code with this `World`'s [`CodeHasher`]. + fn hash_code(&self, code: &[u8]) -> H256 { + Self::CodeHasher::hash(code) + } + /// Update the code for the account at the given address. /// /// Creates a new account at `address` if it does not exist. @@ -404,6 +409,129 @@ impl World for Type2World { } } +#[cfg(not(feature = "cdk_erigon"))] +pub(crate) type StateKey = MptKey; + +#[cfg(feature = "cdk_erigon")] +pub(crate) type StateKey = SmtKey; + +#[cfg(not(feature = "cdk_erigon"))] +pub(crate) type CodeHasher = KeccakHash; + +#[cfg(feature = "cdk_erigon")] +pub(crate) type CodeHasher = PoseidonHash; + +impl World for StateWorld { + type SubtriePath = StateKey; + type CodeHasher = CodeHasher; + + fn contains(&mut self, address: Address) -> anyhow::Result { + match &mut self.state { + Either::Left(type1) => type1.contains(address), + Either::Right(type2) => type2.contains(address), + } + } + fn update_balance( + &mut self, + address: Address, + f: impl FnOnce(&mut U256), + ) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.update_balance(address, f), + Either::Right(type2) => type2.update_balance(address, f), + } + } + fn update_nonce(&mut self, address: Address, f: impl FnOnce(&mut U256)) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.update_nonce(address, f), + Either::Right(type2) => type2.update_nonce(address, f), + } + } + fn set_code(&mut self, address: Address, code: Either<&[u8], H256>) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.set_code(address, code), + Either::Right(type2) => type2.set_code(address, code), + } + } + fn reporting_destroy(&mut self, address: Address) -> anyhow::Result> { + // TODO: Find a way to revamp this + #[cfg(not(feature = "cdk_erigon"))] + match &mut self.state { + Either::Left(type1) => type1.reporting_destroy(address), + Either::Right(_type2) => unreachable!("Type2 is not supported."), + } + #[cfg(feature = "cdk_erigon")] + match &mut self.state { + Either::Left(_type1) => unreachable!("Type1 is not supported"), + Either::Right(type2) => type2.reporting_destroy(address), + } + } + fn create_storage(&mut self, address: Address) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.create_storage(address), + Either::Right(type2) => type2.create_storage(address), + } + } + fn destroy_storage(&mut self, address: Address) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.destroy_storage(address), + Either::Right(type2) => type2.destroy_storage(address), + } + } + fn store_int(&mut self, address: Address, slot: U256, value: U256) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.store_int(address, slot, value), + Either::Right(type2) => type2.store_int(address, slot, value), + } + } + fn store_hash(&mut self, address: Address, hash: H256, value: H256) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.store_hash(address, hash, value), + Either::Right(type2) => type2.store_hash(address, hash, value), + } + } + fn load_int(&mut self, address: Address, slot: U256) -> anyhow::Result { + match &mut self.state { + Either::Left(type1) => type1.load_int(address, slot), + Either::Right(type2) => type2.load_int(address, slot), + } + } + fn reporting_destroy_slot( + &mut self, + address: Address, + slot: U256, + ) -> anyhow::Result> { + match &mut self.state { + Either::Left(type1) => type1.reporting_destroy_slot(address, slot), + Either::Right(type2) => type2.reporting_destroy_slot(address, slot), + } + } + fn mask_storage(&mut self, masks: BTreeMap>) -> anyhow::Result<()> { + match &mut self.state { + Either::Left(type1) => type1.mask_storage(masks), + Either::Right(type2) => type2.mask_storage(masks), + } + } + fn mask(&mut self, paths: impl IntoIterator) -> anyhow::Result<()> { + #[cfg(not(feature = "cdk_erigon"))] + match &mut self.state { + Either::Left(type1) => type1.mask(paths), + Either::Right(_type2) => unreachable!("Type2 is not supported."), + } + #[cfg(feature = "cdk_erigon")] + match &mut self.state { + Either::Left(_type1) => unreachable!("Type1 is not supported"), + Either::Right(type2) => type2.mask(paths), + } + } + fn root(&mut self) -> H256 { + match &mut self.state { + Either::Left(type1) => type1.root(), + Either::Right(type2) => type2.root(), + } + } +} + // Having optional fields here is an odd decision, // but without the distinction, // the wire tests fail. From 3a3e95ee99b261bc41dda7de2a4a7b1d9a25bcb6 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Fri, 8 Nov 2024 17:07:58 -0500 Subject: [PATCH 59/60] Unify entrypoints --- .../src/cpu/kernel/asm/account_code.asm | 23 ++--- .../src/cpu/kernel/asm/balance.asm | 26 +----- .../src/cpu/kernel/asm/cdk_pre_execution.asm | 2 +- .../src/cpu/kernel/asm/core/create.asm | 4 +- .../src/cpu/kernel/asm/core/nonce.asm | 25 +---- .../src/cpu/kernel/asm/core/process_txn.asm | 4 +- .../src/cpu/kernel/asm/core/terminate.asm | 2 +- .../src/cpu/kernel/asm/core/util.asm | 93 +++++++++---------- .../kernel/asm/journal/account_destroyed.asm | 2 +- .../cpu/kernel/asm/journal/code_change.asm | 4 +- .../cpu/kernel/asm/journal/nonce_change.asm | 31 ++----- .../asm/linked_list/accounts_linked_list.asm | 36 ++++++- .../kernel/asm/linked_list/initial_tries.asm | 4 + .../src/cpu/kernel/asm/main.asm | 33 +------ .../src/cpu/kernel/asm/mpt/delete/delete.asm | 2 +- .../asm/mpt/hash/hash_trie_specific.asm | 10 ++ .../asm/mpt/insert/insert_trie_specific.asm | 2 +- .../src/cpu/kernel/asm/mpt/read.asm | 2 +- .../src/cpu/kernel/asm/smt/hash.asm | 6 +- evm_arithmetization/src/witness/transition.rs | 2 +- 20 files changed, 138 insertions(+), 175 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm index 426912653..8e2872de6 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/account_code.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/account_code.asm @@ -22,7 +22,7 @@ extcodehash_dead: %stack (address, kexit_info) -> (kexit_info, 0) EXIT_KERNEL -#[cfg(feature = eth_mainnet)] +#[cfg(not(feature = cdk_erigon))] { global extcodehash: // stack: address, retdest @@ -53,20 +53,17 @@ global extcodehash: %%after: %endmacro -#[cfg(feature = eth_mainnet)] -{ - %macro ext_code_empty - %extcodehash +%macro ext_code_empty + %extcodehash + #[cfg(not(feature = cdk_erigon))] + { %eq_const(@EMPTY_STRING_KECCAK_HASH) - %endmacro -} -#[cfg(feature = cdk_erigon)] -{ - %macro ext_code_empty - %extcodehash + } + #[cfg(feature = cdk_erigon)] + { %eq_const(@EMPTY_STRING_POSEIDON_HASH) - %endmacro -} + } +%endmacro %macro extcodesize %stack (address) -> (address, %%after) diff --git a/evm_arithmetization/src/cpu/kernel/asm/balance.asm b/evm_arithmetization/src/cpu/kernel/asm/balance.asm index 11e1bb441..9d5484ce4 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/balance.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/balance.asm @@ -26,28 +26,10 @@ global sys_balance: %endmacro global balance: - #[cfg(feature = eth_mainnet)] - { - // stack: address, retdest - %mpt_read_state_trie - // stack: account_ptr, retdest - DUP1 ISZERO %jumpi(retzero) // If the account pointer is null, return 0. - %add_const(1) - // stack: balance_ptr, retdest - %mload_trie_data - // stack: balance, retdest - SWAP1 JUMP - } - #[cfg(feature = cdk_erigon)] - { - // stack: address, retdest - %read_balance - // stack: balance, retdest - SWAP1 JUMP - } -retzero: - %stack (account_ptr, retdest) -> (retdest, 0) - JUMP + // stack: address, retdest + %read_balance + // stack: balance, retdest + SWAP1 JUMP global sys_selfbalance: // stack: kexit_info diff --git a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm index 42867abec..5f9f25959 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/cdk_pre_execution.asm @@ -100,7 +100,7 @@ global create_scalable_l2_account: // the code hash // stack: retdest - PUSH @EMPTY_STRING_POSEIDON_HASH + PUSH 0 PUSH @ADDRESS_SCALABLE_L2 %set_code // code hash diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm index 6c1049a31..fb0594d1a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/create.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/create.asm @@ -172,7 +172,7 @@ after_constructor: %returndatasize PUSH @SEGMENT_RETURNDATA GET_CONTEXT %build_address_no_offset // stack: addr, len - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { KECCAK_GENERAL } @@ -264,7 +264,7 @@ create_too_deep: // Pre stack: addr, codehash, redest // Post stack: (empty) global set_codehash: - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { // stack: addr, codehash, retdest DUP1 %insert_touched_addresses diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm index 39b8be23b..62b3d2c90 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/nonce.asm @@ -2,25 +2,10 @@ // Pre stack: address, retdest // Post stack: (empty) global nonce: - #[cfg(feature = eth_mainnet)] - { - // stack: address, retdest - %mpt_read_state_trie - // stack: account_ptr, retdest - // The nonce is the first account field, so we deref the account pointer itself. - // Note: We don't need to handle account_ptr=0, as trie_data[0] = 0, - // so the deref will give 0 (the default nonce) as desired. - %mload_trie_data - // stack: nonce, retdest - SWAP1 JUMP - } - #[cfg(feature = cdk_erigon)] - { - // stack: address, retdest - %read_nonce - // stack: nonce, retdest - SWAP1 JUMP - } + // stack: address, retdest + %read_nonce + // stack: nonce, retdest + SWAP1 JUMP // Convenience macro to call nonce and return where we left off. %macro nonce @@ -31,7 +16,7 @@ global nonce: // Increment the given account's nonce. Assumes the account already exists; panics otherwise. global increment_nonce: - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { // stack: address, retdest DUP1 diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm index 4be6df775..d8f39df5d 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/process_txn.asm @@ -36,7 +36,7 @@ global process_normalized_txn: // stack: sender, retdest // Assert sender has no code. - DUP1 %ext_code_empty + DUP1 %ext_code_empty %assert_nonzero(invalid_txn_1) // stack: sender, retdest @@ -218,7 +218,7 @@ process_contract_creation_txn_after_ef_check: { %poseidon_hash_code_unpadded } - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { KECCAK_GENERAL } diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm b/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm index 672a4537e..0fe6fe418 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/terminate.asm @@ -86,7 +86,7 @@ global sys_selfdestruct: %stack (kexit_info, balance, address, recipient) -> (balance, address, recipient, kexit_info) // Set the balance of the address to 0. - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { // stack: balance, address, recipient, kexit_info PUSH 0 diff --git a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm index a1a720b63..ee02a615c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/core/util.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/core/util.asm @@ -57,7 +57,7 @@ // Returns 1 if the account is non-existent, 0 otherwise. %macro is_non_existent // stack: addr - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { %mpt_read_state_trie ISZERO } @@ -67,74 +67,69 @@ } %endmacro - // Returns 1 if the account is empty, 0 otherwise. -%macro is_empty - #[cfg(feature = eth_mainnet)] - { +#[cfg(not(feature = cdk_erigon))] +{ + %macro is_empty // stack: addr %mpt_read_state_trie // stack: account_ptr - DUP1 ISZERO - } - #[cfg(feature = cdk_erigon)] - { - // stack: addr - DUP1 %read_nonce - // stack: nonce, addr - ISZERO %not_bit - } - %jumpi(%%false) - #[cfg(feature = eth_mainnet)] - { + DUP1 ISZERO + %jumpi(%%false) + // stack: account_ptr DUP1 %mload_trie_data // stack: nonce, account_ptr + ISZERO %not_bit + %jumpi(%%false) + + %increment DUP1 %mload_trie_data + // stack: balance, balance_ptr ISZERO %not_bit - } - #[cfg(feature = cdk_erigon)] - { + %jumpi(%%false) + + %add_const(2) %mload_trie_data + // stack: code_hash + %eq_const(@EMPTY_STRING_KECCAK_HASH) + %jump(%%after) + + %%false: + // stack: account_ptr + POP + PUSH 0 + %%after: + %endmacro +} + +// Returns 1 if the account is empty, 0 otherwise. +#[cfg(feature = cdk_erigon)] +{ + %macro is_empty // stack: addr DUP1 %read_nonce // stack: nonce, addr ISZERO %not_bit - } - %jumpi(%%false) - #[cfg(feature = eth_mainnet)] - { - %increment DUP1 %mload_trie_data - // stack: balance, balance_ptr - ISZERO %not_bit - } - #[cfg(feature = cdk_erigon)] - { + %jumpi(%%false) + // stack: addr DUP1 %read_balance // stack: balance, addr ISZERO %not_bit - } - %jumpi(%%false) - #[cfg(feature = eth_mainnet)] - { - %add_const(2) %mload_trie_data - // stack: code_hash - PUSH @EMPTY_STRING_KECCAK_HASH - EQ - } - #[cfg(feature = cdk_erigon)] - { + %jumpi(%%false) + // stack: addr %read_code // stack: codehash %eq_const(@EMPTY_STRING_POSEIDON_HASH) - } - %jump(%%after) -%%false: - // stack: account_ptr - POP - PUSH 0 -%%after: -%endmacro + %jump(%%after) + + %%false: + // stack: account_ptr + POP + PUSH 0 + %%after: + %endmacro +} // Returns 1 if the account is dead (i.e., empty or non-existent), 0 otherwise. %macro is_dead 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 15654ad29..1bcafa20b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/account_destroyed.asm @@ -12,7 +12,7 @@ global revert_account_destroyed: PUSH revert_account_destroyed_contd DUP2 %jump(remove_selfdestruct_list) revert_account_destroyed_contd: - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { // stack: address, target, prev_balance, retdest SWAP1 diff --git a/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm b/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm index 6ba5d29df..1e8a90615 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/code_change.asm @@ -1,7 +1,7 @@ // struct CodeChange { address, prev_codehash } %macro journal_add_code_change - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { %journal_add_2(@JOURNAL_ENTRY_CODE_CHANGE) } @@ -12,7 +12,7 @@ %endmacro global revert_code_change: - #[cfg(feature = eth_mainnet)] + #[cfg(not(feature = cdk_erigon))] { // stack: entry_ptr, ptr, retdest POP 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 c5d1f535c..df4af3c7a 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/journal/nonce_change.asm @@ -5,27 +5,10 @@ %endmacro global revert_nonce_change: - #[cfg(feature = eth_mainnet)] - { - // stack: entry_type, ptr, retdest - POP - %journal_load_2 - // stack: address, prev_nonce, retdest - %read_account_from_addr - // stack: payload_ptr, prev_nonce, retdest - DUP1 %assert_nonzero - // stack: nonce_ptr, prev_nonce, retdest - %mstore_trie_data - // stack: retdest - JUMP - } - #[cfg(feature = cdk_erigon)] - { - // stack: entry_type, ptr, retdest - POP - %journal_load_2 - // stack: address, prev_nonce, retdest - %set_nonce - // stack: retdest - JUMP - } + // stack: entry_type, ptr, retdest + POP + %journal_load_2 + // stack: address, prev_nonce, retdest + %set_nonce + // stack: retdest + JUMP diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm index aeba5b0cc..9ffcdd347 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/accounts_linked_list.asm @@ -419,4 +419,38 @@ remove_all_slots_end: // stack: node_ptr %add_const(@ACCOUNTS_LINKED_LISTS_NODE_SIZE) // stack: next_node_ptr -%endmacro \ No newline at end of file +%endmacro + +%macro set_nonce + // stack: address, nonce + %read_account_from_addr + // stack: payload_ptr, nonce + DUP1 %assert_nonzero + // stack: nonce_ptr, nonce + %mstore_trie_data + // stack: (empty) +%endmacro + +%macro read_nonce + // stack: address + %mpt_read_state_trie + // stack: account_ptr + // The nonce is the first account field, so we deref the account pointer itself. + // Note: We don't need to handle account_ptr=0, as trie_data[0] = 0, + // so the deref will give 0 (the default nonce) as desired. + %mload_trie_data + // stack: nonce +%endmacro + +%macro read_balance + // stack: address + %mpt_read_state_trie + // stack: account_ptr + DUP1 ISZERO %jumpi(%%retzero) // If the account pointer is null, return 0. + %add_const(1) + // stack: balance_ptr + %mload_trie_data + // stack: balance +%%retzero: + // stack: 0 +%endmacro diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm index adb8ae468..8791095b2 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm @@ -127,3 +127,7 @@ after_insert_slot: SWAP1 %jump(insert_all_initial_slots) +%macro store_initial_state + %store_initial_accounts + %store_initial_slots +%endmacro \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/asm/main.asm b/evm_arithmetization/src/cpu/kernel/asm/main.asm index 2f4c5013e..1e7643f1b 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/main.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/main.asm @@ -76,15 +76,7 @@ global main: global store_initial: // Store the initial accounts and slots for hashing later - #[cfg(feature = eth_mainnet)] - { - %store_initial_accounts - %store_initial_slots - } - #[cfg(feature = cdk_erigon)] - { - %store_initial_state - } + %store_initial_state global after_store_initial: // Initialize the transaction and receipt trie root pointers. @@ -243,16 +235,7 @@ global check_state_trie: %set_initial_state_trie // stack: trie_data_len - #[cfg(feature = eth_mainnet)] - { - PUSH @INITIAL_RLP_ADDR - // stack: rlp_start, trie_data_len - %mpt_hash_state_trie - } - #[cfg(feature = cdk_erigon)] - { - %smt_hash_state - } + %hash_state_trie // stack: init_state_hash, trie_data_len // Check that the initial trie is correct. @@ -268,17 +251,7 @@ global check_state_trie: global check_final_state_trie: %set_final_tries - #[cfg(feature = eth_mainnet)] - { - PUSH @INITIAL_RLP_ADDR - // stack: rlp_start, dummy_trie_len - %mpt_hash_state_trie - } - #[cfg(feature = cdk_erigon)] - { - %smt_hash_state - } - + %hash_state_trie %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_DIGEST_AFTER) %assert_eq // We don't need the trie data length here. 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 167f56523..9c9a206c2 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/delete/delete.asm @@ -23,7 +23,7 @@ mpt_delete_leaf: PUSH 0 // empty node ptr SWAP1 JUMP -#[cfg(feature = eth_mainnet)] +#[cfg(not(feature = cdk_erigon))] { global delete_account: %addr_to_state_key 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 5bfa2d117..129c3b97f 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 @@ -1,5 +1,15 @@ // Hashing logic specific to a particular trie. +#[cfg(not(feature = cdk_erigon))] +{ + %macro hash_state_trie + // stack: trie_len + PUSH @INITIAL_RLP_ADDR + // stack: rlp_start, dummy_trie_len + %mpt_hash_state_trie + %endmacro +} + global mpt_hash_state_trie: // stack: rlp_start, cur_len, retdest PUSH encode_account diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm index 504e1458d..03fbce3f2 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm @@ -4,7 +4,7 @@ // Pre stack: key, value_ptr, retdest // Post stack: (empty) // TODO: Have this take an address and do %mpt_insert_state_trie? To match mpt_read_state_trie. -#[cfg(feature = eth_mainnet)] +#[cfg(not(feature = cdk_erigon))] { global mpt_insert_state_trie: // stack: key, value_ptr, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm b/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm index 631feb5b3..1c007d98c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm @@ -1,7 +1,7 @@ // Given an address, return a pointer to the associated account data, which // consists of four words (nonce, balance, storage_root, code_hash), in the // trie_data segment. Return null if the address is not found. -#[cfg(feature = eth_mainnet)] +#[cfg(not(feature = cdk_erigon))] { global mpt_read_state_trie: // stack: addr, retdest diff --git a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm index a11f06d69..2d9ec1902 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/smt/hash.asm @@ -1,11 +1,11 @@ -%macro smt_hash_state +%macro hash_state_trie %stack (cur_len) -> (cur_len, %%after) - %jump(smt_hash_state) + %jump(hash_state_trie) %%after: %endmacro // Root hash of the state SMT. -global smt_hash_state: +global hash_state_trie: // stack: cur_len, retdest %mload_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index 30632b860..b4de642ec 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -371,7 +371,7 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o } #[cfg(test)] - if KERNEL.offset_name(pc) == "smt_hash_state" || KERNEL.offset_name(pc) == "sys_sstore" { + if KERNEL.offset_name(pc) == "hash_state_trie" || KERNEL.offset_name(pc) == "sys_sstore" { let mem = state .get_generation_state() .memory From 551011652c238a0fd008f6463075367a2317d687 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Wed, 13 Nov 2024 16:08:14 +0100 Subject: [PATCH 60/60] Fix prepare_interpreter for some type2 tests --- .../kernel/asm/linked_list/initial_tries.asm | 10 +- .../src/cpu/kernel/tests/account_code.rs | 172 +++++++++++++----- .../src/generation/prover_input.rs | 1 - evm_arithmetization/src/witness/transition.rs | 48 ----- evm_arithmetization/src/world.rs | 43 +++++ 5 files changed, 181 insertions(+), 93 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm index 8791095b2..d9b92687c 100644 --- a/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm +++ b/evm_arithmetization/src/cpu/kernel/asm/linked_list/initial_tries.asm @@ -128,6 +128,14 @@ after_insert_slot: %jump(insert_all_initial_slots) %macro store_initial_state + // stack: (empty) + PUSH %%after + %jump(store_initial_state) +%%after: +%endmacro + +global store_initial_state: + // stack: retdest %store_initial_accounts %store_initial_slots -%endmacro \ No newline at end of file + JUMP \ No newline at end of file diff --git a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs index 7abb89e5c..b698ac0df 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/account_code.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/account_code.rs @@ -12,6 +12,8 @@ use plonky2::field::goldilocks_field::GoldilocksField as F; use plonky2::hash::hash_types::RichField; use rand::{thread_rng, Rng}; use smt_trie::code::hash_bytecode_h256; +#[cfg(feature = "cdk_erigon")] +use smt_trie::utils::key2u; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata::{self, GasLimit}; @@ -174,9 +176,14 @@ pub(crate) fn prepare_interpreter( address: Address, account: &EitherAccount, ) -> Result<()> { - let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; + let insert_state_trie = if cfg!(feature = "cdk_erigon") { + KERNEL.global_labels["insert_key"] + } else { + KERNEL.global_labels["insert_account_with_overwrite"] + }; let check_state_trie = KERNEL.global_labels["check_final_state_trie"]; - let mut state_trie: HashedPartialTrie = HashedPartialTrie::from(Node::Empty); + let mut state_trie = StateWorld::default(); + let expected_state_trie_hash = set_account(&mut state_trie, address, &account); let trie_inputs = TrieInputs { state_trie: StateWorld::default(), transactions_trie: HashedPartialTrie::from(Node::Empty), @@ -190,34 +197,80 @@ pub(crate) fn prepare_interpreter( keccak(address.to_fixed_bytes()).as_bytes(), )); // Next, execute mpt_insert_state_trie. - interpreter.generation_state.registers.program_counter = mpt_insert_state_trie; + interpreter.generation_state.registers.program_counter = insert_state_trie; let trie_data = interpreter.get_trie_data_mut(); if trie_data.is_empty() { // In the assembly we skip over 0, knowing trie_data[0] = 0 by default. // Since we don't explicitly set it to 0, we need to do so here. trie_data.push(Some(0.into())); } - let value_ptr = trie_data.len(); - trie_data.push(Some(account.get_nonce())); - trie_data.push(Some(account.get_balance())); - // In memory, storage_root gets interpreted as a pointer to a storage trie, - // so we have to ensure the pointer is valid. It's easiest to set it to 0, - // which works as an empty node, since trie_data[0] = 0 = MPT_TYPE_EMPTY. - trie_data.push(Some(H256::zero().into_uint())); - trie_data.push(Some(account.get_code_hash_u256())); - let trie_data_len = trie_data.len().into(); - interpreter.set_global_metadata_field(GlobalMetadata::TrieDataSize, trie_data_len); - interpreter - .push(0xDEADBEEFu32.into()) - .expect("The stack should not overflow"); - interpreter - .push(value_ptr.into()) - .expect("The stack should not overflow"); // value_ptr - interpreter - .push(k.try_into().unwrap()) - .expect("The stack should not overflow"); // key - interpreter.run()?; + #[cfg(feature = "cdk_erigon")] + { + let right_state_trie = state_trie + .state + .expect_right("cdk_erigon expects SMTs.") + .as_smt(); + let mut kv_sorted_by_k: Vec<(U256, U256)> = right_state_trie + .kv_store + .iter() + .map(|(&key, &val)| (key2u(key), val)) + .collect(); + kv_sorted_by_k.sort_by(|(k1, _), (k2, _)| k1.cmp(k2)); + + trie_data.extend( + right_state_trie + .to_vec_skip_empty_node_and_add_offset(2) + .iter() + .map(|v| Some(*v)), + ); + + let trie_data_len = trie_data.len().into(); + interpreter.set_global_metadata_field(GlobalMetadata::TrieDataSize, trie_data_len); + let accounts_list_next_pointer = Segment::AccountsLinkedList as usize + 4; + interpreter.set_global_metadata_field( + GlobalMetadata::AccountsLinkedListNextAvailable, + accounts_list_next_pointer.into(), + ); + + for (key, v) in kv_sorted_by_k { + interpreter.generation_state.registers.program_counter = insert_state_trie; + + interpreter + .push(0xDEADBEEFu32.into()) + .expect("The stack should not overflow"); + interpreter.push(v).expect("The stack should not overflow"); // value + interpreter + .push(key) + .expect("The stack should not overflow"); // key + interpreter.run()?; + } + } + #[cfg(not(feature = "cdk_erigon"))] + { + let value_ptr = trie_data.len(); + trie_data.push(Some(account.get_nonce())); + trie_data.push(Some(account.get_balance())); + // In memory, storage_root gets interpreted as a pointer to a storage trie, + // so we have to ensure the pointer is valid. It's easiest to set it to 0, + // which works as an empty node, since trie_data[0] = 0 = MPT_TYPE_EMPTY. + trie_data.push(Some(H256::zero().into_uint())); + trie_data.push(Some(account.get_code_hash_u256())); + let trie_data_len = trie_data.len().into(); + interpreter.set_global_metadata_field(GlobalMetadata::TrieDataSize, trie_data_len); + + interpreter + .push(0xDEADBEEFu32.into()) + .expect("The stack should not overflow"); + interpreter + .push(value_ptr.into()) + // .push(0.into()) + .expect("The stack should not overflow"); // value_ptr + interpreter + .push(k.try_into().unwrap()) + .expect("The stack should not overflow"); // key + interpreter.run()?; + } assert_eq!( interpreter.stack().len(), @@ -230,39 +283,25 @@ pub(crate) fn prepare_interpreter( interpreter .push(0xDEADBEEFu32.into()) .expect("The stack should not overflow"); - interpreter - .push((Segment::StorageLinkedList as usize + 5).into()) - .expect("The stack should not overflow"); - interpreter - .push(interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot)) - .unwrap(); - interpreter - .push((Segment::AccountsLinkedList as usize + 4).into()) - .expect("The stack should not overflow"); // Now, set the payload. interpreter.generation_state.registers.program_counter = - KERNEL.global_labels["insert_all_initial_accounts"]; + KERNEL.global_labels["store_initial_state"]; interpreter.run()?; - assert_eq!(interpreter.stack_len(), 1); - - let state_root = interpreter.pop().expect("The stack should not be empty"); - interpreter.set_global_metadata_field(GlobalMetadata::StateTrieRoot, state_root); + assert_eq!(interpreter.stack_len(), 0); - // Now, execute `mpt_hash_state_trie`. - state_trie.insert(k, account.rlp_encode().to_vec())?; - let expected_state_trie_hash = state_trie.hash(); + // Now, hash the initial state trie. interpreter.set_global_metadata_field( - GlobalMetadata::StateTrieRootDigestAfter, - h2u(expected_state_trie_hash), + GlobalMetadata::StateTrieRootDigestBefore, + expected_state_trie_hash, ); interpreter.generation_state.registers.program_counter = check_state_trie; interpreter .halt_offsets - .push(KERNEL.global_labels["check_txn_trie"]); + .push(KERNEL.global_labels["check_final_state_trie"]); interpreter .push(0xDEADBEEFu32.into()) .expect("The stack should not overflow"); @@ -727,3 +766,50 @@ fn sload() -> Result<()> { fn init_logger() { let _ = try_init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info")); } + +fn set_account(world: &mut StateWorld, addr: Address, account: &EitherAccount) -> U256 { + use plonky2::field::types::PrimeField64; + use smt_trie::{ + keys::{key_balance, key_code_length}, + utils::hashout2u, + }; + + use crate::world::World; + + match &mut world.state { + Either::Left(type1world) => { + let state_trie = type1world.state_trie_mut(); + let k = nibbles_64(U256::from_big_endian( + keccak(addr.to_fixed_bytes()).as_bytes(), + )); + let _ = state_trie.insert(k, account.as_mpt_account().rlp_encode().to_vec()); + h2u(state_trie.hash()) + } + Either::Right(type2world) => { + let acct = account.as_smt_account(); + let key = key_balance(addr); + log::debug!( + "setting {:?} balance to {:?}, the key is {:?}", + addr, + account.get_balance(), + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); + let _ = type2world.update_balance(addr, |b| *b = account.get_balance()); + + let _ = type2world.update_balance(addr, |b| *b = account.get_balance()); + let _ = type2world.update_nonce(addr, |n| *n = account.get_nonce()); + type2world.set_code_and_hash( + addr, + Either::Right(acct.code_hash), + Some(acct.code_length), + ); + let key = key_code_length(addr); + log::debug!( + "setting {:?} code length, the key is {:?}", + addr, + U256(std::array::from_fn(|i| key.0[i].to_canonical_u64())) + ); + hashout2u(type2world.as_smt().root) + } + } +} diff --git a/evm_arithmetization/src/generation/prover_input.rs b/evm_arithmetization/src/generation/prover_input.rs index b3be8f1a4..c27b90dfc 100644 --- a/evm_arithmetization/src/generation/prover_input.rs +++ b/evm_arithmetization/src/generation/prover_input.rs @@ -129,7 +129,6 @@ impl GenerationState { content: new_content, }, ); - // } n }, Ok, diff --git a/evm_arithmetization/src/witness/transition.rs b/evm_arithmetization/src/witness/transition.rs index b4de642ec..c65dd7e18 100644 --- a/evm_arithmetization/src/witness/transition.rs +++ b/evm_arithmetization/src/witness/transition.rs @@ -322,54 +322,6 @@ pub(crate) fn log_kernel_instruction>(state: &mut S, o ), ); - #[cfg(all(test, not(feature = "cdk_erigon")))] - if KERNEL.offset_name(pc) == "mpt_hash_state_trie" || KERNEL.offset_name(pc) == "init" { - let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::TrieData); - log::debug!( - "account nonce = {:?} balance {:?} code hash {:?}", - mem[5], - mem[6], - mem[8] - ); - let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::AccountsLinkedList); - log::debug!( - "accounts linked list = {:?}", - LinkedList::<4>::from_mem_and_segment(&mem, Segment::AccountsLinkedList) - ); - - let mem = state - .get_generation_state() - .memory - .get_preinit_memory(Segment::StorageLinkedList); - log::debug!( - "storage linked list = {:?}", - LinkedList::<5>::from_mem_and_segment(&mem, Segment::StorageLinkedList) - ); - - let state_trie_ptr = u256_to_usize( - state - .get_generation_state() - .memory - .read_global_metadata(GlobalMetadata::StateTrieRoot), - ) - .unwrap(); - - let state_trie = get_state_trie::( - &state.get_generation_state().memory, - state_trie_ptr, - ) - .unwrap(); - - log::debug!("state trie ptr = {:?}", state_trie_ptr); - log::debug!("state trie {:?}", state_trie); - } - #[cfg(test)] if KERNEL.offset_name(pc) == "hash_state_trie" || KERNEL.offset_name(pc) == "sys_sstore" { let mem = state diff --git a/evm_arithmetization/src/world.rs b/evm_arithmetization/src/world.rs index 79e066f6a..efbdd2611 100644 --- a/evm_arithmetization/src/world.rs +++ b/evm_arithmetization/src/world.rs @@ -94,6 +94,15 @@ pub trait World { /// Creates a new account at `address` if it does not exist. fn set_code(&mut self, address: Address, code: Either<&[u8], H256>) -> anyhow::Result<()>; + /// Update the code and code length for the account at the give address. + /// + /// Creates a new account at `address` if it does not exist. + fn set_code_and_hash( + &mut self, + address: Address, + code: Either, + code_length: Option, + ); /// The `core` module of the `trace_decoder` crate tracks required subtries /// for proving. /// @@ -170,6 +179,9 @@ impl Type1World { pub fn state_trie(&self) -> &mpt_trie::partial_trie::HashedPartialTrie { self.state.as_hashed_partial_trie() } + pub fn state_trie_mut(&mut self) -> &mut mpt_trie::partial_trie::HashedPartialTrie { + self.state.as_mut_hashed_partial_trie() + } pub fn into_state_and_storage(self) -> (StateMpt, BTreeMap) { let Self { state, storage } = self; (state, storage) @@ -235,6 +247,16 @@ impl World for Type1World { acct.code_hash = code.right_or_else(Self::CodeHasher::hash); self.state.insert(key, acct) } + fn set_code_and_hash( + &mut self, + address: Address, + code: Either, + _code_length: Option, + ) { + let key = keccak_hash::keccak(address); + let mut acct = self.state.get(key).unwrap_or_default(); + acct.code_hash = code.expect_left("MPTs store hashes as H256."); + } fn reporting_destroy(&mut self, address: Address) -> anyhow::Result> { self.state.reporting_remove(address) } @@ -344,6 +366,16 @@ impl World for Type2World { }; Ok(()) } + fn set_code_and_hash( + &mut self, + address: Address, + code: Either, + code_length: Option, + ) { + let acct = self.accounts.entry(address).or_default(); + acct.code_hash = Some(code.expect_right("SMTs store hashes as U256.")); + acct.code_length = code_length; + } fn reporting_destroy(&mut self, address: Address) -> anyhow::Result> { self.accounts.remove(&address); Ok(None) @@ -453,6 +485,17 @@ impl World for StateWorld { Either::Right(type2) => type2.set_code(address, code), } } + fn set_code_and_hash( + &mut self, + address: Address, + code_hash: Either, + code_length: Option, + ) { + match &mut self.state { + Either::Left(type1) => type1.set_code_and_hash(address, code_hash, code_length), + Either::Right(type2) => type2.set_code_and_hash(address, code_hash, code_length), + } + } fn reporting_destroy(&mut self, address: Address) -> anyhow::Result> { // TODO: Find a way to revamp this #[cfg(not(feature = "cdk_erigon"))]