From 51ee7599e4eced5e040685917bdb1adf3adc4eac Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 6 Aug 2025 17:47:45 +0200 Subject: [PATCH 01/37] AccountId and new state, changes to JournalInner --- crates/context/src/journal/entry.rs | 136 +++--- crates/context/src/journal/inner.rs | 286 +++++++------ crates/primitives/src/address.rs | 113 +++++ crates/primitives/src/lib.rs | 2 + crates/state/src/account.rs | 524 +++++++++++++++++++++++ crates/state/src/lib.rs | 631 +--------------------------- crates/state/src/storage.rs | 109 +++++ crates/state/src/types.rs | 208 ++++++++- 8 files changed, 1185 insertions(+), 824 deletions(-) create mode 100644 crates/primitives/src/address.rs create mode 100644 crates/state/src/account.rs create mode 100644 crates/state/src/storage.rs diff --git a/crates/context/src/journal/entry.rs b/crates/context/src/journal/entry.rs index 00b5f17219..e37c5e9b7c 100644 --- a/crates/context/src/journal/entry.rs +++ b/crates/context/src/journal/entry.rs @@ -5,60 +5,60 @@ //! They are created when there is change to the state from loading (making it warm), changes to the balance, //! or removal of the storage slot. Check [`JournalEntryTr`] for more details. -use primitives::{Address, StorageKey, StorageValue, KECCAK_EMPTY, PRECOMPILE3, U256}; +use primitives::{AccountId, Address, StorageKey, StorageValue, KECCAK_EMPTY, PRECOMPILE3, U256}; use state::{EvmState, TransientStorage}; /// Trait for tracking and reverting state changes in the EVM. /// Journal entry contains information about state changes that can be reverted. pub trait JournalEntryTr { /// Creates a journal entry for when an account is accessed and marked as "warm" for gas metering - fn account_warmed(address: Address) -> Self; + fn account_warmed(account_id: AccountId) -> Self; /// Creates a journal entry for when an account is destroyed via SELFDESTRUCT /// Records the target address that received the destroyed account's balance, /// whether the account was already destroyed, and its balance before destruction /// on revert, the balance is transferred back to the original account fn account_destroyed( - address: Address, - target: Address, + account_id: AccountId, + target: AccountId, destroyed_status: SelfdestructionRevertStatus, had_balance: U256, ) -> Self; /// Creates a journal entry for when an account is "touched" - accessed in a way that may require saving it. /// If account is empty and touch it will be removed from the state (EIP-161 state clear EIP) - fn account_touched(address: Address) -> Self; + fn account_touched(account_id: AccountId) -> Self; /// Creates a journal entry for a balance transfer between accounts - fn balance_transfer(from: Address, to: Address, balance: U256) -> Self; + fn balance_transfer(from: AccountId, to: AccountId, balance: U256) -> Self; /// Creates a journal entry for when an account's balance is changed. - fn balance_changed(address: Address, old_balance: U256) -> Self; + fn balance_changed(account_id: AccountId, old_balance: U256) -> Self; /// Creates a journal entry for when an account's nonce is incremented. - fn nonce_changed(address: Address) -> Self; + fn nonce_changed(account_id: AccountId) -> Self; /// Creates a journal entry for when a new account is created - fn account_created(address: Address, is_created_globally: bool) -> Self; + fn account_created(account_id: AccountId, is_created_globally: bool) -> Self; /// Creates a journal entry for when a storage slot is modified /// Records the previous value for reverting - fn storage_changed(address: Address, key: StorageKey, had_value: StorageValue) -> Self; + fn storage_changed(account_id: AccountId, key: StorageKey, had_value: StorageValue) -> Self; /// Creates a journal entry for when a storage slot is accessed and marked as "warm" for gas metering /// This is called with SLOAD opcode. - fn storage_warmed(address: Address, key: StorageKey) -> Self; + fn storage_warmed(account_id: AccountId, key: StorageKey) -> Self; /// Creates a journal entry for when a transient storage slot is modified (EIP-1153) /// Records the previous value for reverting fn transient_storage_changed( - address: Address, + account_id: AccountId, key: StorageKey, had_value: StorageValue, ) -> Self; /// Creates a journal entry for when an account's code is modified - fn code_changed(address: Address) -> Self; + fn code_changed(account_id: AccountId) -> Self; /// Reverts the state change recorded by this journal entry /// @@ -215,76 +215,87 @@ pub enum JournalEntry { }, } impl JournalEntryTr for JournalEntry { - fn account_warmed(address: Address) -> Self { - JournalEntry::AccountWarmed { address } + fn account_warmed(account_id: AccountId) -> Self { + // JournalEntry::AccountWarmed { account_id } + todo!() } fn account_destroyed( - address: Address, - target: Address, + account_id: AccountId, + target: AccountId, destroyed_status: SelfdestructionRevertStatus, had_balance: StorageValue, ) -> Self { - JournalEntry::AccountDestroyed { - address, - target, - destroyed_status, - had_balance, - } + // JournalEntry::AccountDestroyed { + // address, + // target, + // destroyed_status, + // had_balance, + // } + todo!() } - fn account_touched(address: Address) -> Self { - JournalEntry::AccountTouched { address } + fn account_touched(account_id: AccountId) -> Self { + // JournalEntry::AccountTouched { account_id } + todo!() } - fn balance_changed(address: Address, old_balance: U256) -> Self { - JournalEntry::BalanceChange { - address, - old_balance, - } + fn balance_changed(account_id: AccountId, old_balance: U256) -> Self { + // JournalEntry::BalanceChange { + // account_id, + // old_balance, + // } + todo!() } - fn balance_transfer(from: Address, to: Address, balance: U256) -> Self { - JournalEntry::BalanceTransfer { from, to, balance } + fn balance_transfer(from: AccountId, to: AccountId, balance: U256) -> Self { + // JournalEntry::BalanceTransfer { from, to, balance } + todo!() } - fn account_created(address: Address, is_created_globally: bool) -> Self { - JournalEntry::AccountCreated { - address, - is_created_globally, - } + fn account_created(account_id: AccountId, is_created_globally: bool) -> Self { + // JournalEntry::AccountCreated { + // account_id, + // is_created_globally, + // } + todo!() } - fn storage_changed(address: Address, key: StorageKey, had_value: StorageValue) -> Self { - JournalEntry::StorageChanged { - address, - key, - had_value, - } + fn storage_changed(account_id: AccountId, key: StorageKey, had_value: StorageValue) -> Self { + // JournalEntry::StorageChanged { + // account_id, + // key, + // had_value, + // } + todo!() } - fn nonce_changed(address: Address) -> Self { - JournalEntry::NonceChange { address } + fn nonce_changed(account_id: AccountId) -> Self { + // JournalEntry::NonceChange { account_id } + todo!() } - fn storage_warmed(address: Address, key: StorageKey) -> Self { - JournalEntry::StorageWarmed { address, key } + fn storage_warmed(account_id: AccountId, key: StorageKey) -> Self { + // JournalEntry::StorageWarmed { account_id, key } + todo!() } fn transient_storage_changed( - address: Address, + account_id: AccountId, key: StorageKey, had_value: StorageValue, ) -> Self { - JournalEntry::TransientStorageChange { - address, - key, - had_value, - } + // JournalEntry::TransientStorageChange { + // address, + // key, + // had_value, + // } + todo!() } - fn code_changed(address: Address) -> Self { - JournalEntry::CodeChange { address } + fn code_changed(account_id: AccountId) -> Self { + // JournalEntry::CodeChange { account_id } + todo!() } fn revert( @@ -392,13 +403,14 @@ impl JournalEntryTr for JournalEntry { return; }; let tkey = (address, key); - if had_value.is_zero() { - // if previous value is zero, remove it - transient_storage.remove(&tkey); - } else { - // if not zero, reinsert old value to transient storage. - transient_storage.insert(tkey, had_value); - } + // if had_value.is_zero() { + // // if previous value is zero, remove it + // transient_storage.remove(&tkey); + // } else { + // // if not zero, reinsert old value to transient storage. + // transient_storage.insert(tkey, had_value); + // } + todo!() } JournalEntry::CodeChange { address } => { let acc = state.get_mut(&address).unwrap(); diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a7cefb75a3..99eaa19546 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -12,9 +12,10 @@ use database_interface::Database; use primitives::{ hardfork::SpecId::{self, *}, hash_map::Entry, - Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, + AccountId, Address, AddressAndId, AddressOrId, HashMap, Log, StorageKey, StorageValue, B256, + KECCAK_EMPTY, U256, }; -use state::{Account, EvmState, EvmStorageSlot, TransientStorage}; +use state::{Account, EvmState, EvmStateNew, EvmStorageSlot, TransientStorage}; use std::vec::Vec; /// Inner journal state that contains journal and state changes. /// @@ -24,6 +25,8 @@ use std::vec::Vec; pub struct JournalInner { /// The current state pub state: EvmState, + /// The current state new + pub state_new: EvmStateNew, /// Transient storage that is discarded after every transaction. /// /// See [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153). @@ -71,6 +74,7 @@ impl JournalInner { pub fn new() -> JournalInner { Self { state: HashMap::default(), + state_new: EvmStateNew::new(), transient_storage: TransientStorage::default(), logs: Vec::new(), journal: Vec::default(), @@ -99,6 +103,7 @@ impl JournalInner { // missing any field. let Self { state, + state_new, transient_storage, logs, depth, @@ -128,6 +133,7 @@ impl JournalInner { // if there is no journal entries, there has not been any changes. let Self { state, + state_new, transient_storage, logs, depth, @@ -160,6 +166,7 @@ impl JournalInner { // missing any field. let Self { state, + state_new, transient_storage, logs, depth, @@ -202,17 +209,17 @@ impl JournalInner { /// This is especially important for state clear where touched empty accounts needs to /// be removed from state. #[inline] - pub fn touch(&mut self, address: Address) { - if let Some(account) = self.state.get_mut(&address) { - Self::touch_account(&mut self.journal, address, account); + pub fn touch(&mut self, address_or_id: &AddressOrId) { + if let Some((account, id)) = self.state_new.get_mut(address_or_id) { + Self::touch_account(&mut self.journal, id.id(), account); } } /// Mark account as touched. #[inline] - fn touch_account(journal: &mut Vec, address: Address, account: &mut Account) { + fn touch_account(journal: &mut Vec, id: AccountId, account: &mut Account) { if !account.is_touched() { - journal.push(ENTRY::account_touched(address)); + journal.push(ENTRY::account_touched(id)); account.mark_touch(); } } @@ -225,21 +232,21 @@ impl JournalInner { /// /// Panics if the account has not been loaded and is missing from the state set. #[inline] - pub fn account(&self, address: Address) -> &Account { - self.state - .get(&address) - .expect("Account expected to be loaded") // Always assume that acc is already loaded + pub fn account(&self, address_or_id: &AddressOrId) -> (&Account, AddressAndId) { + self.state_new + .get(&address_or_id) + .expect("Account expected to be loaded") // Always assume that acc is already loaded. } /// Set code and its hash to the account. /// /// Note: Assume account is warm and that hash is calculated from code. #[inline] - pub fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) { - let account = self.state.get_mut(&address).unwrap(); - Self::touch_account(&mut self.journal, address, account); + pub fn set_code_with_hash(&mut self, address_or_id: AddressOrId, code: Bytecode, hash: B256) { + let (account, address) = self.state_new.get_mut(&address_or_id).unwrap(); + Self::touch_account(&mut self.journal, address.id(), account); - self.journal.push(ENTRY::code_changed(address)); + self.journal.push(ENTRY::code_changed(address.id())); account.info.code_hash = hash; account.info.code = Some(code); @@ -251,35 +258,35 @@ impl JournalInner { /// /// In case of EIP-7702 code with zero address, the bytecode will be erased. #[inline] - pub fn set_code(&mut self, address: Address, code: Bytecode) { + pub fn set_code(&mut self, address_or_id: AddressOrId, code: Bytecode) { if let Bytecode::Eip7702(eip7702_bytecode) = &code { if eip7702_bytecode.address().is_zero() { - self.set_code_with_hash(address, Bytecode::default(), KECCAK_EMPTY); + self.set_code_with_hash(address_or_id, Bytecode::default(), KECCAK_EMPTY); return; } } let hash = code.hash_slow(); - self.set_code_with_hash(address, code, hash) + self.set_code_with_hash(address_or_id, code, hash) } /// Add journal entry for caller accounting. #[inline] pub fn caller_accounting_journal_entry( &mut self, - address: Address, + address_or_id: AddressOrId, old_balance: U256, bump_nonce: bool, ) { + let id = self.state_new.get_id(&address_or_id).unwrap(); // account balance changed. - self.journal - .push(ENTRY::balance_changed(address, old_balance)); + self.journal.push(ENTRY::balance_changed(id, old_balance)); // account is touched. - self.journal.push(ENTRY::account_touched(address)); + self.journal.push(ENTRY::account_touched(id)); if bump_nonce { // nonce changed. - self.journal.push(ENTRY::nonce_changed(address)); + self.journal.push(ENTRY::nonce_changed(id)); } } @@ -290,29 +297,31 @@ impl JournalInner { pub fn balance_incr( &mut self, db: &mut DB, - address: Address, + address_or_id: AddressOrId, balance: U256, ) -> Result<(), DB::Error> { - let account = self.load_account(db, address)?.data; + let (account, address) = self.load_account(db, address_or_id)?.data; let old_balance = account.info.balance; account.info.balance = account.info.balance.saturating_add(balance); // march account as touched. if !account.is_touched() { account.mark_touch(); - self.journal.push(ENTRY::account_touched(address)); + self.journal.push(ENTRY::account_touched(address.id())); } // add journal entry for balance increment. self.journal - .push(ENTRY::balance_changed(address, old_balance)); + .push(ENTRY::balance_changed(address.id(), old_balance)); Ok(()) } /// Increments the nonce of the account. #[inline] - pub fn nonce_bump_journal_entry(&mut self, address: Address) { - self.journal.push(ENTRY::nonce_changed(address)); + pub fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId) { + // TODO check if it is okay to unwrap here + let id = self.state_new.get_id(&address_or_id).unwrap(); + self.journal.push(ENTRY::nonce_changed(id)); } /// Transfers balance from two accounts. Returns error if sender balance is not enough. @@ -320,23 +329,23 @@ impl JournalInner { pub fn transfer( &mut self, db: &mut DB, - from: Address, - to: Address, + from: AddressOrId, + to: AddressOrId, balance: U256, ) -> Result, DB::Error> { if balance.is_zero() { self.load_account(db, to)?; - let to_account = self.state.get_mut(&to).unwrap(); - Self::touch_account(&mut self.journal, to, to_account); + let (to_account, to) = self.state_new.get_mut(&to).unwrap(); + Self::touch_account(&mut self.journal, to.id(), to_account); return Ok(None); } // load accounts - self.load_account(db, from)?; - self.load_account(db, to)?; + let (_, to) = self.load_account(db, to)?.data; + let (_, from) = self.load_account(db, from)?.data; // sub balance from - let from_account = self.state.get_mut(&from).unwrap(); - Self::touch_account(&mut self.journal, from, from_account); + let (from_account, from) = self.state_new.get_mut(&AddressOrId::Id(from.id())).unwrap(); + Self::touch_account(&mut self.journal, from.id(), from_account); let from_balance = &mut from_account.info.balance; let Some(from_balance_decr) = from_balance.checked_sub(balance) else { @@ -345,8 +354,8 @@ impl JournalInner { *from_balance = from_balance_decr; // add balance to - let to_account = &mut self.state.get_mut(&to).unwrap(); - Self::touch_account(&mut self.journal, to, to_account); + let (to_account, to) = self.state_new.get_mut(&AddressOrId::Id(to.id())).unwrap(); + Self::touch_account(&mut self.journal, to.id(), to_account); let to_balance = &mut to_account.info.balance; let Some(to_balance_incr) = to_balance.checked_add(balance) else { return Ok(Some(TransferError::OverflowPayment)); @@ -355,7 +364,7 @@ impl JournalInner { // Overflow of U256 balance is not possible to happen on mainnet. We don't bother to return funds from from_acc. self.journal - .push(ENTRY::balance_transfer(from, to, balance)); + .push(ENTRY::balance_transfer(from.id(), to.id(), balance)); Ok(None) } @@ -378,7 +387,7 @@ impl JournalInner { #[inline] pub fn create_account_checkpoint( &mut self, - caller: Address, + caller: AddressOrId, target_address: Address, balance: U256, spec_id: SpecId, @@ -387,7 +396,8 @@ impl JournalInner { let checkpoint = self.checkpoint(); // Fetch balance of caller. - let caller_balance = self.state.get(&caller).unwrap().info.balance; + let (caller_acc, caller) = self.state_new.get(&caller).unwrap(); + let caller_balance = caller_acc.info.balance; // Check if caller has enough balance to send to the created contract. if caller_balance < balance { self.checkpoint_revert(checkpoint); @@ -395,7 +405,10 @@ impl JournalInner { } // Newly created account is present, as we just loaded it. - let target_acc = self.state.get_mut(&target_address).unwrap(); + let (target_acc, target) = self + .state_new + .get_mut(&AddressOrId::Address(target_address)) + .unwrap(); let last_journal = &mut self.journal; // New account can be created if: @@ -411,7 +424,7 @@ impl JournalInner { let is_created_globally = target_acc.mark_created_locally(); // this entry will revert set nonce. - last_journal.push(ENTRY::account_created(target_address, is_created_globally)); + last_journal.push(ENTRY::account_created(target.id(), is_created_globally)); target_acc.info.code = None; // EIP-161: State trie clearing (invariant-preserving alternative) if spec_id.is_enabled_in(SPURIOUS_DRAGON) { @@ -421,7 +434,7 @@ impl JournalInner { // touch account. This is important as for pre SpuriousDragon account could be // saved even empty. - Self::touch_account(last_journal, target_address, target_acc); + Self::touch_account(last_journal, target.id(), target_acc); // Add balance to created account, as we already have target here. let Some(new_balance) = target_acc.info.balance.checked_add(balance) else { @@ -431,10 +444,15 @@ impl JournalInner { target_acc.info.balance = new_balance; // safe to decrement for the caller as balance check is already done. - self.state.get_mut(&caller).unwrap().info.balance -= balance; + self.state_new + .get_mut(&AddressOrId::Id(caller.id())) + .unwrap() + .0 + .info + .balance -= balance; // add journal entry of transferred balance - last_journal.push(ENTRY::balance_transfer(caller, target_address, balance)); + last_journal.push(ENTRY::balance_transfer(caller.id(), target.id(), balance)); Ok(checkpoint) } @@ -489,25 +507,27 @@ impl JournalInner { pub fn selfdestruct( &mut self, db: &mut DB, - address: Address, + address_or_id: AddressOrId, target: Address, ) -> Result, DB::Error> { + // TODO re check this logic let spec = self.spec; - let account_load = self.load_account(db, target)?; + let account_load = self.load_account(db, AddressOrId::Address(target))?; let is_cold = account_load.is_cold; - let is_empty = account_load.state_clear_aware_is_empty(spec); + let is_empty = account_load.0.state_clear_aware_is_empty(spec); + let target = account_load.1; - if address != target { + let (acc, address) = self.state_new.get_mut(&address_or_id).unwrap(); + if address.address() != target.address() { // Both accounts are loaded before this point, `address` as we execute its contract. // and `target` at the beginning of the function. - let acc_balance = self.state.get(&address).unwrap().info.balance; + let acc_balance = acc.info.balance; - let target_account = self.state.get_mut(&target).unwrap(); - Self::touch_account(&mut self.journal, target, target_account); + let target_account = self.state.get_mut(target.address()).unwrap(); + Self::touch_account(&mut self.journal, address.id(), target_account); target_account.info.balance += acc_balance; } - let acc = self.state.get_mut(&address).unwrap(); let balance = acc.info.balance; let destroyed_status = if !acc.is_selfdestructed() { @@ -525,14 +545,14 @@ impl JournalInner { acc.mark_selfdestructed_locally(); acc.info.balance = U256::ZERO; Some(ENTRY::account_destroyed( - address, - target, + address.id(), + target.id(), destroyed_status, balance, )) - } else if address != target { + } else if address.address() != target.address() { acc.info.balance = U256::ZERO; - Some(ENTRY::balance_transfer(address, target, balance)) + Some(ENTRY::balance_transfer(address.id(), target.id(), balance)) } else { // State is not changed: // * if we are after Cancun upgrade and @@ -561,9 +581,9 @@ impl JournalInner { pub fn load_account( &mut self, db: &mut DB, - address: Address, - ) -> Result, DB::Error> { - self.load_account_optional(db, address, false, []) + address_or_id: AddressOrId, + ) -> Result, DB::Error> { + self.load_account_optional(db, address_or_id, false, []) } /// Loads account into memory. If account is EIP-7702 type it will additionally @@ -577,12 +597,12 @@ impl JournalInner { pub fn load_account_delegated( &mut self, db: &mut DB, - address: Address, + address_or_id: AddressOrId, ) -> Result, DB::Error> { let spec = self.spec; let is_eip7702_enabled = spec.is_enabled_in(SpecId::PRAGUE); - let account = self.load_account_optional(db, address, is_eip7702_enabled, [])?; - let is_empty = account.state_clear_aware_is_empty(spec); + let account = self.load_account_optional(db, address_or_id, is_eip7702_enabled, [])?; + let is_empty = account.0.state_clear_aware_is_empty(spec); let mut account_load = StateLoad::new( AccountLoad { @@ -593,9 +613,9 @@ impl JournalInner { ); // load delegate code if account is EIP-7702 - if let Some(Bytecode::Eip7702(code)) = &account.info.code { + if let Some(Bytecode::Eip7702(code)) = &account.0.info.code { let address = code.address(); - let delegate_account = self.load_account(db, address)?; + let delegate_account = self.load_account(db, AddressOrId::Address(address))?; account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold); } @@ -612,9 +632,9 @@ impl JournalInner { pub fn load_code( &mut self, db: &mut DB, - address: Address, - ) -> Result, DB::Error> { - self.load_account_optional(db, address, true, []) + address_or_id: AddressOrId, + ) -> Result, DB::Error> { + self.load_account_optional(db, address_or_id, true, []) } /// Loads account. If account is already loaded it will be marked as warm. @@ -622,50 +642,53 @@ impl JournalInner { pub fn load_account_optional( &mut self, db: &mut DB, - address: Address, + address_or_id: AddressOrId, load_code: bool, storage_keys: impl IntoIterator, - ) -> Result, DB::Error> { - let load = match self.state.entry(address) { - Entry::Occupied(entry) => { - let account = entry.into_mut(); - let is_cold = account.mark_warm_with_transaction_id(self.transaction_id); - // if it is colad loaded we need to clear local flags that can interact with selfdestruct - if is_cold { - // if it is cold loaded and we have selfdestructed locally it means that - // account was selfdestructed in previous transaction and we need to clear its information and storage. - if account.is_selfdestructed_locally() { - account.selfdestruct(); - account.unmark_selfdestructed_locally(); - } - // unmark locally created - account.unmark_created_locally(); - } - StateLoad { - data: account, - is_cold, - } - } - Entry::Vacant(vac) => { - let account = if let Some(account) = db.basic(address)? { - account.into() - } else { - Account::new_not_existing(self.transaction_id) - }; - - // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account - let is_cold = self.warm_addresses.is_cold(&address); - - StateLoad { - data: vac.insert(account), - is_cold, - } - } - }; + ) -> Result, DB::Error> { + todo!(); + let load = Default::default(); + let id = AddressAndId::new(address_or_id.address().unwrap(), 0); + // let load = match self.state.entry(address) { + // Entry::Occupied(entry) => { + // let account = entry.into_mut(); + // let is_cold = account.mark_warm_with_transaction_id(self.transaction_id); + // // if it is colad loaded we need to clear local flags that can interact with selfdestruct + // if is_cold { + // // if it is cold loaded and we have selfdestructed locally it means that + // // account was selfdestructed in previous transaction and we need to clear its information and storage. + // if account.is_selfdestructed_locally() { + // account.selfdestruct(); + // account.unmark_selfdestructed_locally(); + // } + // // unmark locally created + // account.unmark_created_locally(); + // } + // StateLoad { + // data: account, + // is_cold, + // } + // } + // Entry::Vacant(vac) => { + // let account = if let Some(account) = db.basic(address)? { + // account.into() + // } else { + // Account::new_not_existing(self.transaction_id) + // }; + + // // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account + // let is_cold = self.warm_addresses.is_cold(&address); + + // StateLoad { + // data: vac.insert(account), + // is_cold, + // } + // } + // }; // journal loading of cold account. if load.is_cold { - self.journal.push(ENTRY::account_warmed(address)); + self.journal.push(ENTRY::account_warmed(id.id())); } if load_code { let info = &mut load.data.info; @@ -685,11 +708,11 @@ impl JournalInner { db, &mut self.journal, self.transaction_id, - address, + id, storage_key, )?; } - Ok(load) + Ok((load, id)) } /// Loads storage slot. @@ -701,20 +724,13 @@ impl JournalInner { pub fn sload( &mut self, db: &mut DB, - address: Address, + address_or_id: AddressOrId, key: StorageKey, ) -> Result, DB::Error> { // assume acc is warm - let account = self.state.get_mut(&address).unwrap(); + let (account, id) = self.state_new.get_mut(&address_or_id).unwrap(); // only if account is created in this tx we can assume that storage is empty. - sload_with_account( - account, - db, - &mut self.journal, - self.transaction_id, - address, - key, - ) + sload_with_account(account, db, &mut self.journal, self.transaction_id, id, key) } /// Stores storage slot. @@ -726,13 +742,13 @@ impl JournalInner { pub fn sstore( &mut self, db: &mut DB, - address: Address, + address_or_id: AddressOrId, key: StorageKey, new: StorageValue, ) -> Result, DB::Error> { // assume that acc exists and load the slot. - let present = self.sload(db, address, key)?; - let acc = self.state.get_mut(&address).unwrap(); + let present = self.sload(db, address_or_id, key)?; + let (acc, id) = self.state_new.get_mut(&address_or_id).unwrap(); // if there is no original value in dirty return present value, that is our original. let slot = acc.storage.get_mut(&key).unwrap(); @@ -750,7 +766,7 @@ impl JournalInner { } self.journal - .push(ENTRY::storage_changed(address, key, present.data)); + .push(ENTRY::storage_changed(id.id(), key, present.data)); // insert value into present state. slot.present_value = new; Ok(StateLoad::new( @@ -767,9 +783,10 @@ impl JournalInner { /// /// EIP-1153: Transient storage opcodes #[inline] - pub fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue { + pub fn tload(&mut self, address_or_id: AddressOrId, key: StorageKey) -> StorageValue { + let id = self.state_new.get_id(&address_or_id).unwrap(); self.transient_storage - .get(&(address, key)) + .get(&(id, key)) .copied() .unwrap_or_default() } @@ -781,17 +798,18 @@ impl JournalInner { /// /// EIP-1153: Transient storage opcodes #[inline] - pub fn tstore(&mut self, address: Address, key: StorageKey, new: StorageValue) { + pub fn tstore(&mut self, address_or_id: AddressOrId, key: StorageKey, new: StorageValue) { + let id = self.state_new.get_id(&address_or_id).unwrap(); let had_value = if new.is_zero() { // if new values is zero, remove entry from transient storage. // if previous values was some insert it inside journal. // If it is none nothing should be inserted. - self.transient_storage.remove(&(address, key)) + self.transient_storage.remove(&(id, key)) } else { // insert values let previous_value = self .transient_storage - .insert((address, key), new) + .insert((id, key), new) .unwrap_or_default(); // check if previous value is same @@ -806,7 +824,7 @@ impl JournalInner { if let Some(had_value) = had_value { // insert in journal only if value was changed. self.journal - .push(ENTRY::transient_storage_changed(address, key, had_value)); + .push(ENTRY::transient_storage_changed(id, key, had_value)); } } @@ -824,7 +842,7 @@ pub fn sload_with_account( db: &mut DB, journal: &mut Vec, transaction_id: usize, - address: Address, + address_or_id: AddressAndId, key: StorageKey, ) -> Result, DB::Error> { let is_newly_created = account.is_created(); @@ -839,7 +857,7 @@ pub fn sload_with_account( let value = if is_newly_created { StorageValue::ZERO } else { - db.storage(address, key)? + db.storage(*address_or_id.address(), key)? }; vac.insert(EvmStorageSlot::new(value, transaction_id)); @@ -850,7 +868,7 @@ pub fn sload_with_account( if is_cold { // add it to journal as cold loaded. - journal.push(ENTRY::storage_warmed(address, key)); + journal.push(ENTRY::storage_warmed(address_or_id.id(), key)); } Ok(StateLoad::new(value, is_cold)) diff --git a/crates/primitives/src/address.rs b/crates/primitives/src/address.rs new file mode 100644 index 0000000000..c79ebe0431 --- /dev/null +++ b/crates/primitives/src/address.rs @@ -0,0 +1,113 @@ +//! Contains the [`AddressOrId`] enum, which is used to represent an address or an id. +use crate::Address; + +/// Address id. +pub type AccountId = usize; + +/// Address or account id. Id is used for internal account management. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AddressOrId { + /// An Ethereum address. + Address(Address), + /// Id of account, used for internal account management. + Id(AccountId), +} + +impl Default for AddressOrId { + fn default() -> Self { + Self::Address(Address::default()) + } +} + +impl AddressOrId { + /// Returns true if the address is an Ethereum address. + #[inline] + pub fn is_address(&self) -> bool { + matches!(self, AddressOrId::Address(_)) + } + + /// Returns true if the address is an id. + #[inline] + pub fn is_id(&self) -> bool { + matches!(self, AddressOrId::Id(_)) + } + + /// Returns the address if it is an Ethereum address. + #[inline] + pub fn address(&self) -> Option
{ + if let AddressOrId::Address(address) = self { + Some(*address) + } else { + None + } + } + + /// Returns the id if it is an id. + #[inline] + pub fn as_id(&self) -> Option { + if let AddressOrId::Id(id) = self { + Some(*id) + } else { + None + } + } +} + +/// Address and id. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AddressAndId { + /// Address. + pub address: Address, + /// Id. + pub id: AccountId, +} + +impl AddressAndId { + /// Creates a new address and id. + #[inline] + pub fn new(address: Address, id: AccountId) -> Self { + Self { address, id } + } + + /// Returns the address. + #[inline] + pub fn address(&self) -> &Address { + &self.address + } + + /// Returns the id. + #[inline] + pub fn id(&self) -> AccountId { + self.id + } +} + +/// Address and optional id. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AddressAndOptionalId { + /// Address. + pub address: Address, + /// Id. + pub id: Option, +} + +impl AddressAndOptionalId { + /// Creates a new address and optional id. + #[inline] + pub fn new(address: Address, id: Option) -> Self { + Self { address, id } + } + + /// Converts the address and optional id to an address or id. + #[inline] + pub fn to_address_or_id(&self) -> AddressOrId { + if let Some(id) = self.id { + AddressOrId::Id(id) + } else { + AddressOrId::Address(self.address) + } + } +} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index fd1f0b8c14..193d183094 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -15,6 +15,7 @@ #[cfg(not(feature = "std"))] extern crate alloc as std; +pub mod address; pub mod constants; pub mod eip170; pub mod eip3860; @@ -27,6 +28,7 @@ pub mod eip7918; pub mod hardfork; mod once_lock; +pub use address::{AccountId, AddressAndId, AddressAndOptionalId, AddressOrId}; pub use constants::*; pub use once_lock::OnceLock; diff --git a/crates/state/src/account.rs b/crates/state/src/account.rs new file mode 100644 index 0000000000..a89cc293c6 --- /dev/null +++ b/crates/state/src/account.rs @@ -0,0 +1,524 @@ +//! Account data structures and implementations. + +use crate::{AccountInfo, EvmStorage, EvmStorageSlot}; +use bitflags::bitflags; +use core::hash::Hash; +use primitives::hardfork::SpecId; +use primitives::{Address, HashMap, StorageKey}; + +/// Account type used inside Journal to track changed to state. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Account { + /// Balance, nonce, and code + pub info: AccountInfo, + /// Transaction id, used to track when account was toched/loaded into journal. + pub transaction_id: usize, + /// Storage cache + pub storage: EvmStorage, + /// Account status flags + pub status: AccountStatus, +} + +impl Account { + /// Creates new account and mark it as non existing. + pub fn new_not_existing(transaction_id: usize) -> Self { + Self { + info: AccountInfo::default(), + storage: HashMap::default(), + transaction_id, + status: AccountStatus::LoadedAsNotExisting, + } + } + + /// Checks if account is empty and check if empty state before spurious dragon hardfork. + #[inline] + pub fn state_clear_aware_is_empty(&self, spec: SpecId) -> bool { + if SpecId::is_enabled_in(spec, SpecId::SPURIOUS_DRAGON) { + self.is_empty() + } else { + self.is_loaded_as_not_existing_not_touched() + } + } + + /// Marks the account as self destructed. + pub fn mark_selfdestruct(&mut self) { + self.status |= AccountStatus::SelfDestructed; + } + + /// Unmarks the account as self destructed. + pub fn unmark_selfdestruct(&mut self) { + self.status -= AccountStatus::SelfDestructed; + } + + /// Is account marked for self destruct. + pub fn is_selfdestructed(&self) -> bool { + self.status.contains(AccountStatus::SelfDestructed) + } + + /// Marks the account as touched + pub fn mark_touch(&mut self) { + self.status |= AccountStatus::Touched; + } + + /// Unmarks the touch flag. + pub fn unmark_touch(&mut self) { + self.status -= AccountStatus::Touched; + } + + /// If account status is marked as touched. + pub fn is_touched(&self) -> bool { + self.status.contains(AccountStatus::Touched) + } + + /// Marks the account as newly created. + pub fn mark_created(&mut self) { + self.status |= AccountStatus::Created; + } + + /// Unmarks the created flag. + pub fn unmark_created(&mut self) { + self.status -= AccountStatus::Created; + } + + /// Marks the account as cold. + pub fn mark_cold(&mut self) { + self.status |= AccountStatus::Cold; + } + + /// Marks the account as warm and return true if it was previously cold. + #[inline] + pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { + let same_id = self.transaction_id == transaction_id; + let is_cold = self.status.contains(AccountStatus::Cold); + + self.status -= AccountStatus::Cold; + self.transaction_id = transaction_id; + + if !same_id { + return true; + } + + is_cold + } + + /// Is account locally created + #[inline] + pub fn is_created_locally(&self) -> bool { + self.status.contains(AccountStatus::CreatedLocal) + } + + /// Is account locally selfdestructed + #[inline] + pub fn is_selfdestructed_locally(&self) -> bool { + self.status.contains(AccountStatus::SelfDestructedLocal) + } + + /// Selfdestruct the account by clearing its storage and resetting its account info + #[inline] + pub fn selfdestruct(&mut self) { + self.storage.clear(); + self.info = AccountInfo::default(); + } + + /// Mark account as locally created and mark global created flag. + /// + /// Returns true if it is created globally for first time. + #[inline] + pub fn mark_created_locally(&mut self) -> bool { + self.status |= AccountStatus::CreatedLocal; + let is_created_globaly = !self.status.contains(AccountStatus::Created); + self.status |= AccountStatus::Created; + is_created_globaly + } + + /// Unmark account as locally created + #[inline] + pub fn unmark_created_locally(&mut self) { + self.status -= AccountStatus::CreatedLocal; + } + + /// Mark account as locally and globally selfdestructed + #[inline] + pub fn mark_selfdestructed_locally(&mut self) -> bool { + self.status |= AccountStatus::SelfDestructedLocal; + let is_global_selfdestructed = !self.status.contains(AccountStatus::SelfDestructed); + self.status |= AccountStatus::SelfDestructed; + is_global_selfdestructed + } + + /// Unmark account as locally selfdestructed + #[inline] + pub fn unmark_selfdestructed_locally(&mut self) { + self.status -= AccountStatus::SelfDestructedLocal; + } + + /// Is account loaded as not existing from database. + /// + /// This is needed for pre spurious dragon hardforks where + /// existing and empty were two separate states. + pub fn is_loaded_as_not_existing(&self) -> bool { + self.status.contains(AccountStatus::LoadedAsNotExisting) + } + + /// Is account loaded as not existing from database and not touched. + pub fn is_loaded_as_not_existing_not_touched(&self) -> bool { + self.is_loaded_as_not_existing() && !self.is_touched() + } + + /// Is account newly created in this transaction. + pub fn is_created(&self) -> bool { + self.status.contains(AccountStatus::Created) + } + + /// Is account empty, check if nonce and balance are zero and code is empty. + pub fn is_empty(&self) -> bool { + self.info.is_empty() + } + + /// Returns an iterator over the storage slots that have been changed. + /// + /// See also [EvmStorageSlot::is_changed]. + pub fn changed_storage_slots(&self) -> impl Iterator { + self.storage.iter().filter(|(_, slot)| slot.is_changed()) + } + + /// Sets account info and returns self for method chaining. + pub fn with_info(mut self, info: AccountInfo) -> Self { + self.info = info; + self + } + + /// Populates storage from an iterator of storage slots and returns self for method chaining. + pub fn with_storage(mut self, storage_iter: I) -> Self + where + I: Iterator, + { + for (key, slot) in storage_iter { + self.storage.insert(key, slot); + } + self + } + + /// Marks the account as self destructed and returns self for method chaining. + pub fn with_selfdestruct_mark(mut self) -> Self { + self.mark_selfdestruct(); + self + } + + /// Marks the account as touched and returns self for method chaining. + pub fn with_touched_mark(mut self) -> Self { + self.mark_touch(); + self + } + + /// Marks the account as newly created and returns self for method chaining. + pub fn with_created_mark(mut self) -> Self { + self.mark_created(); + self + } + + /// Marks the account as cold and returns self for method chaining. + pub fn with_cold_mark(mut self) -> Self { + self.mark_cold(); + self + } + + /// Marks the account as warm (not cold) and returns self for method chaining. + /// Also returns whether the account was previously cold. + pub fn with_warm_mark(mut self, transaction_id: usize) -> (Self, bool) { + let was_cold = self.mark_warm_with_transaction_id(transaction_id); + (self, was_cold) + } + + /// Variant of with_warm_mark that doesn't return the previous state. + pub fn with_warm(mut self, transaction_id: usize) -> Self { + self.mark_warm_with_transaction_id(transaction_id); + self + } +} + +impl From for Account { + fn from(info: AccountInfo) -> Self { + Self { + info, + storage: HashMap::default(), + transaction_id: 0, + status: AccountStatus::empty(), + } + } +} + +// The `bitflags!` macro generates `struct`s that manage a set of flags. +bitflags! { + /// Account status flags. Generated by bitflags crate. + /// + /// With multi transaction feature there is a need to have both global and local fields. + /// Global across multiple transaction and local across one transaction execution. + /// + /// Empty state without any flags set represent account that is loaded from db but not interacted with. + /// + /// `Touched` flag is used by database to check if account is potentially changed in some way. + /// Additionally, after EIP-161 touch on empty-existing account would remove this account from state + /// after transaction execution ends. Touch can span across multiple transactions as it is needed + /// to be marked only once so it is safe to have only one global flag. + /// Only first touch have different behaviour from others, and touch in first transaction will invalidate + /// touch functionality in next transactions. + /// + /// `Created` flag is used to mark account as newly created in this transaction. This is used for optimization + /// where if this flag is set we will not access database to fetch storage values. + /// + /// `CreatedLocal` flag is used after cancun to enable selfdestruct cleanup if account is created in same transaction. + /// + /// `Selfdestructed` flag is used to mark account as selfdestructed. On multiple calls this flag is preserved + /// and on revert will stay selfdestructed. + /// + /// `SelfdestructLocal` is needed to award refund on first selfdestruct call. This flag is cleared on account loading. + /// Over multiple transaction account can be selfdestructed in one tx, created in second tx and selfdestructed again in + /// third tx. + /// Additionally if account is loaded in second tx, storage and account that was destroyed in first tx needs to be cleared. + /// + /// `LoadedAsNotExisting` is used to mark account as loaded from database but with `balance == 0 && nonce == 0 && code = 0x`. + /// This flag is fine to span across multiple transactions as it interucts with `Touched` flag this is used in global scope. + /// + /// `CreatedLocal`, `SelfdestructedLocal` and `Cold` flags are reset on first account loading of local scope. + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[cfg_attr(feature = "serde", serde(transparent))] + pub struct AccountStatus: u8 { + /// When account is newly created we will not access database + /// to fetch storage values. + const Created = 0b00000001; + /// When accounts gets loaded this flag is set to false. Create will always be true if CreatedLocal is true. + const CreatedLocal = 0b10000000; + /// If account is marked for self destruction. + const SelfDestructed = 0b00000010; + /// If account is marked for self destruction. + const SelfDestructedLocal = 0b01000000; + /// Only when account is marked as touched we will save it to database. + /// Additionally first touch on empty existing account (After EIP-161) will mark it + /// for removal from state after transaction execution. + const Touched = 0b00000100; + /// used only for pre spurious dragon hardforks where existing and empty were two separate states. + /// it became same state after EIP-161: State trie clearing + const LoadedAsNotExisting = 0b00001000; + /// used to mark account as cold. + /// It is used only in local scope and it is reset on account loading. + const Cold = 0b00010000; + } +} + +impl Default for AccountStatus { + fn default() -> Self { + AccountStatus::empty() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{AccountInfo, EvmStorageSlot}; + use primitives::{HashMap, StorageKey, StorageValue, KECCAK_EMPTY, U256}; + + #[test] + fn account_is_empty_balance() { + let mut account = Account::default(); + assert!(account.is_empty()); + + account.info.balance = U256::from(1); + assert!(!account.is_empty()); + + account.info.balance = U256::ZERO; + assert!(account.is_empty()); + } + + #[test] + fn account_is_empty_nonce() { + let mut account = Account::default(); + assert!(account.is_empty()); + + account.info.nonce = 1; + assert!(!account.is_empty()); + + account.info.nonce = 0; + assert!(account.is_empty()); + } + + #[test] + fn account_is_empty_code_hash() { + let mut account = Account::default(); + assert!(account.is_empty()); + + account.info.code_hash = [1; 32].into(); + assert!(!account.is_empty()); + + account.info.code_hash = [0; 32].into(); + assert!(account.is_empty()); + + account.info.code_hash = KECCAK_EMPTY; + assert!(account.is_empty()); + } + + #[test] + fn account_state() { + let mut account = Account::default(); + + assert!(!account.is_touched()); + assert!(!account.is_selfdestructed()); + + account.mark_touch(); + assert!(account.is_touched()); + assert!(!account.is_selfdestructed()); + + account.mark_selfdestruct(); + assert!(account.is_touched()); + assert!(account.is_selfdestructed()); + + account.unmark_selfdestruct(); + assert!(account.is_touched()); + assert!(!account.is_selfdestructed()); + } + + #[test] + fn account_is_cold() { + let mut account = Account::default(); + + // Account is not cold by default + assert!(!account.status.contains(AccountStatus::Cold)); + + // When marking warm account as warm again, it should return false + assert!(!account.mark_warm_with_transaction_id(0)); + + // Mark account as cold + account.mark_cold(); + + // Account is cold + assert!(account.status.contains(AccountStatus::Cold)); + + // When marking cold account as warm, it should return true + assert!(account.mark_warm_with_transaction_id(0)); + } + + #[test] + fn test_account_with_info() { + let info = AccountInfo::default(); + let account = Account::default().with_info(info.clone()); + + assert_eq!(account.info, info); + assert_eq!(account.storage, HashMap::default()); + assert_eq!(account.status, AccountStatus::empty()); + } + + #[test] + fn test_account_with_storage() { + let mut storage = HashMap::new(); + let key1 = StorageKey::from(1); + let key2 = StorageKey::from(2); + let slot1 = EvmStorageSlot::new(StorageValue::from(10), 0); + let slot2 = EvmStorageSlot::new(StorageValue::from(20), 0); + + storage.insert(key1, slot1.clone()); + storage.insert(key2, slot2.clone()); + + let account = Account::default().with_storage(storage.clone().into_iter()); + + assert_eq!(account.storage.len(), 2); + assert_eq!(account.storage.get(&key1), Some(&slot1)); + assert_eq!(account.storage.get(&key2), Some(&slot2)); + } + + #[test] + fn test_account_with_selfdestruct_mark() { + let account = Account::default().with_selfdestruct_mark(); + + assert!(account.is_selfdestructed()); + assert!(!account.is_touched()); + assert!(!account.is_created()); + } + + #[test] + fn test_account_with_touched_mark() { + let account = Account::default().with_touched_mark(); + + assert!(!account.is_selfdestructed()); + assert!(account.is_touched()); + assert!(!account.is_created()); + } + + #[test] + fn test_account_with_created_mark() { + let account = Account::default().with_created_mark(); + + assert!(!account.is_selfdestructed()); + assert!(!account.is_touched()); + assert!(account.is_created()); + } + + #[test] + fn test_account_with_cold_mark() { + let account = Account::default().with_cold_mark(); + + assert!(account.status.contains(AccountStatus::Cold)); + } + + #[test] + fn test_account_with_warm_mark() { + // Start with a cold account + let cold_account = Account::default().with_cold_mark(); + assert!(cold_account.status.contains(AccountStatus::Cold)); + + // Use with_warm_mark to warm it + let (warm_account, was_cold) = cold_account.with_warm_mark(0); + + // Check that it's now warm and previously was cold + assert!(!warm_account.status.contains(AccountStatus::Cold)); + assert!(was_cold); + + // Try with an already warm account + let (still_warm_account, was_cold) = warm_account.with_warm_mark(0); + assert!(!still_warm_account.status.contains(AccountStatus::Cold)); + assert!(!was_cold); + } + + #[test] + fn test_account_with_warm() { + // Start with a cold account + let cold_account = Account::default().with_cold_mark(); + assert!(cold_account.status.contains(AccountStatus::Cold)); + + // Use with_warm to warm it + let warm_account = cold_account.with_warm(0); + + // Check that it's now warm + assert!(!warm_account.status.contains(AccountStatus::Cold)); + } + + #[test] + fn test_account_builder_chaining() { + let info = AccountInfo { + nonce: 5, + ..AccountInfo::default() + }; + + let slot_key = StorageKey::from(42); + let slot_value = EvmStorageSlot::new(StorageValue::from(123), 0); + let mut storage = HashMap::new(); + storage.insert(slot_key, slot_value.clone()); + + // Chain multiple builder methods together + let account = Account::default() + .with_info(info.clone()) + .with_storage(storage.into_iter()) + .with_created_mark() + .with_touched_mark() + .with_cold_mark() + .with_warm(0); + + // Verify all modifications were applied + assert_eq!(account.info, info); + assert_eq!(account.storage.get(&slot_key), Some(&slot_value)); + assert!(account.is_created()); + assert!(account.is_touched()); + assert!(!account.status.contains(AccountStatus::Cold)); + } +} diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index d10af7eac3..020ee0337f 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -2,633 +2,14 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] +mod account; mod account_info; +mod storage; mod types; -pub use bytecode; +pub use account::{Account, AccountStatus}; pub use account_info::AccountInfo; -pub use bytecode::Bytecode; +pub use bytecode::{self, Bytecode}; pub use primitives; -pub use types::{EvmState, EvmStorage, TransientStorage}; - -use bitflags::bitflags; -use core::hash::Hash; -use primitives::hardfork::SpecId; -use primitives::{HashMap, StorageKey, StorageValue}; - -/// Account type used inside Journal to track changed to state. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Account { - /// Balance, nonce, and code - pub info: AccountInfo, - /// Transaction id, used to track when account was toched/loaded into journal. - pub transaction_id: usize, - /// Storage cache - pub storage: EvmStorage, - /// Account status flags - pub status: AccountStatus, -} - -impl Account { - /// Creates new account and mark it as non existing. - pub fn new_not_existing(transaction_id: usize) -> Self { - Self { - info: AccountInfo::default(), - storage: HashMap::default(), - transaction_id, - status: AccountStatus::LoadedAsNotExisting, - } - } - - /// Checks if account is empty and check if empty state before spurious dragon hardfork. - #[inline] - pub fn state_clear_aware_is_empty(&self, spec: SpecId) -> bool { - if SpecId::is_enabled_in(spec, SpecId::SPURIOUS_DRAGON) { - self.is_empty() - } else { - self.is_loaded_as_not_existing_not_touched() - } - } - - /// Marks the account as self destructed. - pub fn mark_selfdestruct(&mut self) { - self.status |= AccountStatus::SelfDestructed; - } - - /// Unmarks the account as self destructed. - pub fn unmark_selfdestruct(&mut self) { - self.status -= AccountStatus::SelfDestructed; - } - - /// Is account marked for self destruct. - pub fn is_selfdestructed(&self) -> bool { - self.status.contains(AccountStatus::SelfDestructed) - } - - /// Marks the account as touched - pub fn mark_touch(&mut self) { - self.status |= AccountStatus::Touched; - } - - /// Unmarks the touch flag. - pub fn unmark_touch(&mut self) { - self.status -= AccountStatus::Touched; - } - - /// If account status is marked as touched. - pub fn is_touched(&self) -> bool { - self.status.contains(AccountStatus::Touched) - } - - /// Marks the account as newly created. - pub fn mark_created(&mut self) { - self.status |= AccountStatus::Created; - } - - /// Unmarks the created flag. - pub fn unmark_created(&mut self) { - self.status -= AccountStatus::Created; - } - - /// Marks the account as cold. - pub fn mark_cold(&mut self) { - self.status |= AccountStatus::Cold; - } - - /// Marks the account as warm and return true if it was previously cold. - #[inline] - pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { - let same_id = self.transaction_id == transaction_id; - let is_cold = self.status.contains(AccountStatus::Cold); - - self.status -= AccountStatus::Cold; - self.transaction_id = transaction_id; - - if !same_id { - return true; - } - - is_cold - } - - /// Is account locally created - #[inline] - pub fn is_created_locally(&self) -> bool { - self.status.contains(AccountStatus::CreatedLocal) - } - - /// Is account locally selfdestructed - #[inline] - pub fn is_selfdestructed_locally(&self) -> bool { - self.status.contains(AccountStatus::SelfDestructedLocal) - } - - /// Selfdestruct the account by clearing its storage and resetting its account info - #[inline] - pub fn selfdestruct(&mut self) { - self.storage.clear(); - self.info = AccountInfo::default(); - } - - /// Mark account as locally created and mark global created flag. - /// - /// Returns true if it is created globally for first time. - #[inline] - pub fn mark_created_locally(&mut self) -> bool { - self.status |= AccountStatus::CreatedLocal; - let is_created_globaly = !self.status.contains(AccountStatus::Created); - self.status |= AccountStatus::Created; - is_created_globaly - } - - /// Unmark account as locally created - #[inline] - pub fn unmark_created_locally(&mut self) { - self.status -= AccountStatus::CreatedLocal; - } - - /// Mark account as locally and globally selfdestructed - #[inline] - pub fn mark_selfdestructed_locally(&mut self) -> bool { - self.status |= AccountStatus::SelfDestructedLocal; - let is_global_selfdestructed = !self.status.contains(AccountStatus::SelfDestructed); - self.status |= AccountStatus::SelfDestructed; - is_global_selfdestructed - } - - /// Unmark account as locally selfdestructed - #[inline] - pub fn unmark_selfdestructed_locally(&mut self) { - self.status -= AccountStatus::SelfDestructedLocal; - } - - /// Is account loaded as not existing from database. - /// - /// This is needed for pre spurious dragon hardforks where - /// existing and empty were two separate states. - pub fn is_loaded_as_not_existing(&self) -> bool { - self.status.contains(AccountStatus::LoadedAsNotExisting) - } - - /// Is account loaded as not existing from database and not touched. - pub fn is_loaded_as_not_existing_not_touched(&self) -> bool { - self.is_loaded_as_not_existing() && !self.is_touched() - } - - /// Is account newly created in this transaction. - pub fn is_created(&self) -> bool { - self.status.contains(AccountStatus::Created) - } - - /// Is account empty, check if nonce and balance are zero and code is empty. - pub fn is_empty(&self) -> bool { - self.info.is_empty() - } - - /// Returns an iterator over the storage slots that have been changed. - /// - /// See also [EvmStorageSlot::is_changed]. - pub fn changed_storage_slots(&self) -> impl Iterator { - self.storage.iter().filter(|(_, slot)| slot.is_changed()) - } - - /// Sets account info and returns self for method chaining. - pub fn with_info(mut self, info: AccountInfo) -> Self { - self.info = info; - self - } - - /// Populates storage from an iterator of storage slots and returns self for method chaining. - pub fn with_storage(mut self, storage_iter: I) -> Self - where - I: Iterator, - { - for (key, slot) in storage_iter { - self.storage.insert(key, slot); - } - self - } - - /// Marks the account as self destructed and returns self for method chaining. - pub fn with_selfdestruct_mark(mut self) -> Self { - self.mark_selfdestruct(); - self - } - - /// Marks the account as touched and returns self for method chaining. - pub fn with_touched_mark(mut self) -> Self { - self.mark_touch(); - self - } - - /// Marks the account as newly created and returns self for method chaining. - pub fn with_created_mark(mut self) -> Self { - self.mark_created(); - self - } - - /// Marks the account as cold and returns self for method chaining. - pub fn with_cold_mark(mut self) -> Self { - self.mark_cold(); - self - } - - /// Marks the account as warm (not cold) and returns self for method chaining. - /// Also returns whether the account was previously cold. - pub fn with_warm_mark(mut self, transaction_id: usize) -> (Self, bool) { - let was_cold = self.mark_warm_with_transaction_id(transaction_id); - (self, was_cold) - } - - /// Variant of with_warm_mark that doesn't return the previous state. - pub fn with_warm(mut self, transaction_id: usize) -> Self { - self.mark_warm_with_transaction_id(transaction_id); - self - } -} - -impl From for Account { - fn from(info: AccountInfo) -> Self { - Self { - info, - storage: HashMap::default(), - transaction_id: 0, - status: AccountStatus::empty(), - } - } -} - -// The `bitflags!` macro generates `struct`s that manage a set of flags. -bitflags! { - /// Account status flags. Generated by bitflags crate. - /// - /// With multi transaction feature there is a need to have both global and local fields. - /// Global across multiple transaction and local across one transaction execution. - /// - /// Empty state without any flags set represent account that is loaded from db but not interacted with. - /// - /// `Touched` flag is used by database to check if account is potentially changed in some way. - /// Additionally, after EIP-161 touch on empty-existing account would remove this account from state - /// after transaction execution ends. Touch can span across multiple transactions as it is needed - /// to be marked only once so it is safe to have only one global flag. - /// Only first touch have different behaviour from others, and touch in first transaction will invalidate - /// touch functionality in next transactions. - /// - /// `Created` flag is used to mark account as newly created in this transaction. This is used for optimization - /// where if this flag is set we will not access database to fetch storage values. - /// - /// `CreatedLocal` flag is used after cancun to enable selfdestruct cleanup if account is created in same transaction. - /// - /// `Selfdestructed` flag is used to mark account as selfdestructed. On multiple calls this flag is preserved - /// and on revert will stay selfdestructed. - /// - /// `SelfdestructLocal` is needed to award refund on first selfdestruct call. This flag is cleared on account loading. - /// Over multiple transaction account can be selfdestructed in one tx, created in second tx and selfdestructed again in - /// third tx. - /// Additionally if account is loaded in second tx, storage and account that was destroyed in first tx needs to be cleared. - /// - /// `LoadedAsNotExisting` is used to mark account as loaded from database but with `balance == 0 && nonce == 0 && code = 0x`. - /// This flag is fine to span across multiple transactions as it interucts with `Touched` flag this is used in global scope. - /// - /// `CreatedLocal`, `SelfdestructedLocal` and `Cold` flags are reset on first account loading of local scope. - #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] - #[cfg_attr(feature = "serde", serde(transparent))] - pub struct AccountStatus: u8 { - /// When account is newly created we will not access database - /// to fetch storage values. - const Created = 0b00000001; - /// When accounts gets loaded this flag is set to false. Create will always be true if CreatedLocal is true. - const CreatedLocal = 0b10000000; - /// If account is marked for self destruction. - const SelfDestructed = 0b00000010; - /// If account is marked for self destruction. - const SelfDestructedLocal = 0b01000000; - /// Only when account is marked as touched we will save it to database. - /// Additionally first touch on empty existing account (After EIP-161) will mark it - /// for removal from state after transaction execution. - const Touched = 0b00000100; - /// used only for pre spurious dragon hardforks where existing and empty were two separate states. - /// it became same state after EIP-161: State trie clearing - const LoadedAsNotExisting = 0b00001000; - /// used to mark account as cold. - /// It is used only in local scope and it is reset on account loading. - const Cold = 0b00010000; - } -} - -impl Default for AccountStatus { - fn default() -> Self { - AccountStatus::empty() - } -} - -/// This type keeps track of the current value of a storage slot. -#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct EvmStorageSlot { - /// Original value of the storage slot - pub original_value: StorageValue, - /// Present value of the storage slot - pub present_value: StorageValue, - /// Transaction id, used to track when storage slot was made warm. - pub transaction_id: usize, - /// Represents if the storage slot is cold - pub is_cold: bool, -} - -impl EvmStorageSlot { - /// Creates a new _unchanged_ `EvmStorageSlot` for the given value. - pub fn new(original: StorageValue, transaction_id: usize) -> Self { - Self { - original_value: original, - present_value: original, - transaction_id, - is_cold: false, - } - } - - /// Creates a new _changed_ `EvmStorageSlot`. - pub fn new_changed( - original_value: StorageValue, - present_value: StorageValue, - transaction_id: usize, - ) -> Self { - Self { - original_value, - present_value, - transaction_id, - is_cold: false, - } - } - /// Returns true if the present value differs from the original value. - pub fn is_changed(&self) -> bool { - self.original_value != self.present_value - } - - /// Returns the original value of the storage slot. - #[inline] - pub fn original_value(&self) -> StorageValue { - self.original_value - } - - /// Returns the current value of the storage slot. - #[inline] - pub fn present_value(&self) -> StorageValue { - self.present_value - } - - /// Marks the storage slot as cold. Does not change transaction_id. - #[inline] - pub fn mark_cold(&mut self) { - self.is_cold = true; - } - - /// Marks the storage slot as warm and sets transaction_id to the given value - /// - /// - /// Returns false if old transition_id is different from given id or in case they are same return `Self::is_cold` value. - #[inline] - pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { - let same_id = self.transaction_id == transaction_id; - self.transaction_id = transaction_id; - let was_cold = core::mem::replace(&mut self.is_cold, false); - - if same_id { - // only if transaction id is same we are returning was_cold. - return was_cold; - } - true - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::EvmStorageSlot; - use primitives::{StorageKey, KECCAK_EMPTY, U256}; - - #[test] - fn account_is_empty_balance() { - let mut account = Account::default(); - assert!(account.is_empty()); - - account.info.balance = U256::from(1); - assert!(!account.is_empty()); - - account.info.balance = U256::ZERO; - assert!(account.is_empty()); - } - - #[test] - fn account_is_empty_nonce() { - let mut account = Account::default(); - assert!(account.is_empty()); - - account.info.nonce = 1; - assert!(!account.is_empty()); - - account.info.nonce = 0; - assert!(account.is_empty()); - } - - #[test] - fn account_is_empty_code_hash() { - let mut account = Account::default(); - assert!(account.is_empty()); - - account.info.code_hash = [1; 32].into(); - assert!(!account.is_empty()); - - account.info.code_hash = [0; 32].into(); - assert!(account.is_empty()); - - account.info.code_hash = KECCAK_EMPTY; - assert!(account.is_empty()); - } - - #[test] - fn account_state() { - let mut account = Account::default(); - - assert!(!account.is_touched()); - assert!(!account.is_selfdestructed()); - - account.mark_touch(); - assert!(account.is_touched()); - assert!(!account.is_selfdestructed()); - - account.mark_selfdestruct(); - assert!(account.is_touched()); - assert!(account.is_selfdestructed()); - - account.unmark_selfdestruct(); - assert!(account.is_touched()); - assert!(!account.is_selfdestructed()); - } - - #[test] - fn account_is_cold() { - let mut account = Account::default(); - - // Account is not cold by default - assert!(!account.status.contains(crate::AccountStatus::Cold)); - - // When marking warm account as warm again, it should return false - assert!(!account.mark_warm_with_transaction_id(0)); - - // Mark account as cold - account.mark_cold(); - - // Account is cold - assert!(account.status.contains(crate::AccountStatus::Cold)); - - // When marking cold account as warm, it should return true - assert!(account.mark_warm_with_transaction_id(0)); - } - - #[test] - fn test_account_with_info() { - let info = AccountInfo::default(); - let account = Account::default().with_info(info.clone()); - - assert_eq!(account.info, info); - assert_eq!(account.storage, HashMap::default()); - assert_eq!(account.status, AccountStatus::empty()); - } - - #[test] - fn test_account_with_storage() { - let mut storage = HashMap::new(); - let key1 = StorageKey::from(1); - let key2 = StorageKey::from(2); - let slot1 = EvmStorageSlot::new(StorageValue::from(10), 0); - let slot2 = EvmStorageSlot::new(StorageValue::from(20), 0); - - storage.insert(key1, slot1.clone()); - storage.insert(key2, slot2.clone()); - - let account = Account::default().with_storage(storage.clone().into_iter()); - - assert_eq!(account.storage.len(), 2); - assert_eq!(account.storage.get(&key1), Some(&slot1)); - assert_eq!(account.storage.get(&key2), Some(&slot2)); - } - - #[test] - fn test_account_with_selfdestruct_mark() { - let account = Account::default().with_selfdestruct_mark(); - - assert!(account.is_selfdestructed()); - assert!(!account.is_touched()); - assert!(!account.is_created()); - } - - #[test] - fn test_account_with_touched_mark() { - let account = Account::default().with_touched_mark(); - - assert!(!account.is_selfdestructed()); - assert!(account.is_touched()); - assert!(!account.is_created()); - } - - #[test] - fn test_account_with_created_mark() { - let account = Account::default().with_created_mark(); - - assert!(!account.is_selfdestructed()); - assert!(!account.is_touched()); - assert!(account.is_created()); - } - - #[test] - fn test_account_with_cold_mark() { - let account = Account::default().with_cold_mark(); - - assert!(account.status.contains(AccountStatus::Cold)); - } - - #[test] - fn test_storage_mark_warm_with_transaction_id() { - let mut slot = EvmStorageSlot::new(U256::ZERO, 0); - slot.is_cold = true; - slot.transaction_id = 0; - assert!(slot.mark_warm_with_transaction_id(1)); - - slot.is_cold = false; - slot.transaction_id = 0; - assert!(slot.mark_warm_with_transaction_id(1)); - - slot.is_cold = true; - slot.transaction_id = 1; - assert!(slot.mark_warm_with_transaction_id(1)); - - slot.is_cold = false; - slot.transaction_id = 1; - // Only if transaction id is same and is_cold is false, return false. - assert!(!slot.mark_warm_with_transaction_id(1)); - } - - #[test] - fn test_account_with_warm_mark() { - // Start with a cold account - let cold_account = Account::default().with_cold_mark(); - assert!(cold_account.status.contains(AccountStatus::Cold)); - - // Use with_warm_mark to warm it - let (warm_account, was_cold) = cold_account.with_warm_mark(0); - - // Check that it's now warm and previously was cold - assert!(!warm_account.status.contains(AccountStatus::Cold)); - assert!(was_cold); - - // Try with an already warm account - let (still_warm_account, was_cold) = warm_account.with_warm_mark(0); - assert!(!still_warm_account.status.contains(AccountStatus::Cold)); - assert!(!was_cold); - } - - #[test] - fn test_account_with_warm() { - // Start with a cold account - let cold_account = Account::default().with_cold_mark(); - assert!(cold_account.status.contains(AccountStatus::Cold)); - - // Use with_warm to warm it - let warm_account = cold_account.with_warm(0); - - // Check that it's now warm - assert!(!warm_account.status.contains(AccountStatus::Cold)); - } - - #[test] - fn test_account_builder_chaining() { - let info = AccountInfo { - nonce: 5, - ..AccountInfo::default() - }; - - let slot_key = StorageKey::from(42); - let slot_value = EvmStorageSlot::new(StorageValue::from(123), 0); - let mut storage = HashMap::new(); - storage.insert(slot_key, slot_value.clone()); - - // Chain multiple builder methods together - let account = Account::default() - .with_info(info.clone()) - .with_storage(storage.into_iter()) - .with_created_mark() - .with_touched_mark() - .with_cold_mark() - .with_warm(0); - - // Verify all modifications were applied - assert_eq!(account.info, info); - assert_eq!(account.storage.get(&slot_key), Some(&slot_value)); - assert!(account.is_created()); - assert!(account.is_touched()); - assert!(!account.status.contains(AccountStatus::Cold)); - } -} +pub use storage::EvmStorageSlot; +pub use types::{EvmState, EvmStateNew, EvmStorage, TransientStorage}; diff --git a/crates/state/src/storage.rs b/crates/state/src/storage.rs new file mode 100644 index 0000000000..3ea71a6635 --- /dev/null +++ b/crates/state/src/storage.rs @@ -0,0 +1,109 @@ +//! Storage slot data structures and implementations. + +use primitives::StorageValue; + +/// This type keeps track of the current value of a storage slot. +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EvmStorageSlot { + /// Original value of the storage slot + pub original_value: StorageValue, + /// Present value of the storage slot + pub present_value: StorageValue, + /// Transaction id, used to track when storage slot was made warm. + pub transaction_id: usize, + /// Represents if the storage slot is cold + pub is_cold: bool, +} + +impl EvmStorageSlot { + /// Creates a new _unchanged_ `EvmStorageSlot` for the given value. + pub fn new(original: StorageValue, transaction_id: usize) -> Self { + Self { + original_value: original, + present_value: original, + transaction_id, + is_cold: false, + } + } + + /// Creates a new _changed_ `EvmStorageSlot`. + pub fn new_changed( + original_value: StorageValue, + present_value: StorageValue, + transaction_id: usize, + ) -> Self { + Self { + original_value, + present_value, + transaction_id, + is_cold: false, + } + } + /// Returns true if the present value differs from the original value. + pub fn is_changed(&self) -> bool { + self.original_value != self.present_value + } + + /// Returns the original value of the storage slot. + #[inline] + pub fn original_value(&self) -> StorageValue { + self.original_value + } + + /// Returns the current value of the storage slot. + #[inline] + pub fn present_value(&self) -> StorageValue { + self.present_value + } + + /// Marks the storage slot as cold. Does not change transaction_id. + #[inline] + pub fn mark_cold(&mut self) { + self.is_cold = true; + } + + /// Marks the storage slot as warm and sets transaction_id to the given value + /// + /// + /// Returns false if old transition_id is different from given id or in case they are same return `Self::is_cold` value. + #[inline] + pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { + let same_id = self.transaction_id == transaction_id; + self.transaction_id = transaction_id; + let was_cold = core::mem::replace(&mut self.is_cold, false); + + if same_id { + // only if transaction id is same we are returning was_cold. + return was_cold; + } + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + use primitives::U256; + + #[test] + fn test_storage_mark_warm_with_transaction_id() { + let mut slot = EvmStorageSlot::new(U256::ZERO, 0); + slot.is_cold = true; + slot.transaction_id = 0; + assert!(slot.mark_warm_with_transaction_id(1)); + + slot.is_cold = false; + slot.transaction_id = 0; + assert!(slot.mark_warm_with_transaction_id(1)); + + slot.is_cold = true; + slot.transaction_id = 1; + assert!(slot.mark_warm_with_transaction_id(1)); + + slot.is_cold = false; + slot.transaction_id = 1; + // Only if transaction id is same and is_cold is false, return false. + assert!(!slot.mark_warm_with_transaction_id(1)); + } +} diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 7c656428ba..c3bf94dc1e 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -1,11 +1,213 @@ -use super::{Account, EvmStorageSlot}; -use primitives::{Address, HashMap, StorageKey, StorageValue}; +use crate::{Account, EvmStorageSlot}; +use primitives::{ + AccountId, Address, AddressAndId, AddressOrId, HashMap, StorageKey, StorageValue, +}; /// EVM State is a mapping from addresses to accounts. pub type EvmState = HashMap; /// Structure used for EIP-1153 transient storage -pub type TransientStorage = HashMap<(Address, StorageKey), StorageValue>; +pub type TransientStorage = HashMap<(AccountId, StorageKey), StorageValue>; /// An account's Storage is a mapping from 256-bit integer keys to [EvmStorageSlot]s. pub type EvmStorage = HashMap; + +/// EVM State with internal account management. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct EvmStateNew { + /// Index of accounts. + pub index: HashMap, + /// Accounts. + /// TODO make pushing of new account smarter and introduce a Vec of Vec so we dont need to clone it. + pub accounts: Vec<(Account, Address)>, +} + +impl EvmStateNew { + /// Create a new empty state. + pub fn new() -> Self { + Self { + index: HashMap::default(), + accounts: Vec::new(), + } + } + + /// Get the account id for an address or id. + pub fn get_id(&self, address_or_id: &AddressOrId) -> Option { + match address_or_id { + AddressOrId::Id(id) => Some(*id), + AddressOrId::Address(address) => self.index.get(address).copied(), + } + } + + /// Get an immutable reference to an account by address. + pub fn get(&self, address_or_id: &AddressOrId) -> Option<(&Account, AddressAndId)> { + match address_or_id { + AddressOrId::Id(id) => self + .accounts + .get(*id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))), + AddressOrId::Address(address) => self.index.get(address).and_then(|id| { + self.accounts + .get(*id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) + }), + } + } + + /// Get a mutable reference to an account by address. + pub fn get_mut(&mut self, address_or_id: &AddressOrId) -> Option<(&mut Account, AddressAndId)> { + match address_or_id { + AddressOrId::Id(id) => self + .accounts + .get_mut(*id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))), + AddressOrId::Address(address) => self.index.get(address).and_then(|id| { + self.accounts + .get_mut(*id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) + }), + } + } + + /// Insert a new account or update an existing one. + pub fn insert(&mut self, address: Address, account: Account) -> AddressAndId { + todo!() + // match self.index.get(&address) { + // Some(&id) => { + // // Update existing account + // let old_account = std::mem::replace(&mut self.accounts[id], (account, address)); + // Some(old_account) + // } + // None => { + // // Insert new account + // let id = self.accounts.len(); + // self.accounts.push((account, address)); + // self.index.insert(address, id); + // None + // } + // } + } + + /// Remove an account by address. + pub fn remove(&mut self, address: &Address) -> Option { + todo!() + // self.index.remove(address).and_then(|id| { + // // Note: This doesn't actually remove from the Vec to avoid invalidating indices. + // // The account at this index becomes invalid and shouldn't be accessed directly. + // // A proper implementation might mark it as deleted or use a different data structure. + // self.accounts.get(id).cloned() + // }) + } + + /// Check if an account exists. + pub fn contains_key(&self, address: &Address) -> bool { + self.index.contains_key(address) + } + + /// Get the number of accounts. + pub fn len(&self) -> usize { + self.index.len() + } + + /// Check if the state is empty. + pub fn is_empty(&self) -> bool { + self.index.is_empty() + } + + /// Clear all accounts. + pub fn clear(&mut self) { + self.index.clear(); + self.accounts.clear(); + } + + /// Iterate over all accounts. + pub fn iter(&self) -> impl Iterator + '_ { + self.accounts.iter() + } + /// Iterate mutably over all accounts. + /// Returns a vector of (Address, &mut Account) pairs. + /// + /// Note: This collects addresses into a Vec to avoid borrowing issues. + pub fn iter_mut(&mut self) -> Vec<(Address, &mut Account)> { + todo!() + // let mut result = Vec::new(); + // let addresses: Vec<(Address, AccountId)> = + // self.index.iter().map(|(k, &v)| (*k, v)).collect(); + + // // We need to use unsafe here to get multiple mutable references + // // This is safe because we know each AccountId maps to a unique index + // for (addr, id) in addresses { + // if let Some(account) = self.accounts.get_mut(id) { + // result.push((addr, account as *mut Account)); + // } + // } + + // // Convert raw pointers back to references + // result + // .into_iter() + // .map(|(addr, ptr)| unsafe { (addr, &mut *ptr) }) + // .collect() + } + + // /// Get a mutable reference to an account, inserting a default if it doesn't exist. + // pub fn get_or_insert_default(&mut self, address: Address) -> &mut Account { + // if !self.contains_key(&address) { + // self.insert(address, Account::default()); + // } + // self.get_mut(&address).unwrap() + // } + + // /// Get a mutable reference to an account, inserting with a function if it doesn't exist. + // pub fn get_or_insert_with(&mut self, address_or_id: &AddressOrId, f: F) -> &mut Account + // where + // F: FnOnce() -> Account, + // { + // if !self.contains_key(&address) { + // self.insert(address, f()); + // } + // self.get_mut(&address).unwrap() + // } + + // /// Take ownership of the state, returning the underlying HashMap. + // pub fn take(&mut self) -> HashMap { + // let mut map = HashMap::new(); + // let index = std::mem::take(&mut self.index); + // let accounts = std::mem::take(&mut self.accounts); + + // for (address, id) in index { + // if let Some(account) = accounts.get(id) { + // map.insert(address, account.clone()); + // } + // } + // map + // } +} + +impl Default for EvmStateNew { + fn default() -> Self { + Self::new() + } +} + +impl From> for EvmStateNew { + fn from(map: HashMap) -> Self { + let mut state = EvmStateNew::new(); + for (address, account) in map { + state.insert(address, account); + } + state + } +} + +// impl From for HashMap { +// fn from(state: EvmStateNew) -> Self { +// let mut map = HashMap::new(); +// for (address, id) in state.index { +// if let Some(account) = state.accounts.get(id) { +// map.insert(address, account.clone()); +// } +// } +// map +// } +// } From fd57eebfcce344b440e1005d1a0fd016cb9cf048 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 8 Aug 2025 15:44:58 +0200 Subject: [PATCH 02/37] continue work on transition to address and id --- crates/context/interface/src/host.rs | 52 +++++---- .../context/interface/src/journaled_state.rs | 90 ++++++++-------- crates/context/src/context.rs | 42 +++++--- crates/context/src/journal.rs | 87 ++++++++------- crates/context/src/journal/inner.rs | 73 +++++++------ crates/handler/src/frame.rs | 101 +++++++++++++----- crates/handler/src/frame_data.rs | 8 +- .../interpreter/src/instructions/contract.rs | 20 ++-- crates/interpreter/src/instructions/host.rs | 36 ++++--- crates/interpreter/src/instructions/system.rs | 2 + .../interpreter/src/instructions/utility.rs | 2 +- crates/interpreter/src/interpreter/input.rs | 14 +-- .../src/interpreter_action/call_inputs.rs | 12 +-- .../src/interpreter_action/create_inputs.rs | 7 +- crates/interpreter/src/interpreter_types.rs | 7 +- crates/primitives/src/address.rs | 40 +++++-- 16 files changed, 363 insertions(+), 230 deletions(-) diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index 636a5eb4dc..ced2f42c1a 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -5,7 +5,7 @@ use crate::{ journaled_state::AccountLoad, }; use auto_impl::auto_impl; -use primitives::{Address, Bytes, Log, StorageKey, StorageValue, B256, U256}; +use primitives::{Address, AddressOrId, Bytes, Log, StorageKey, StorageValue, B256, U256}; /// Host trait with all methods that are needed by the Interpreter. /// @@ -59,7 +59,7 @@ pub trait Host { /// Selfdestruct account, calls `ContextTr::journal_mut().selfdestruct(address, target)` fn selfdestruct( &mut self, - address: Address, + address_or_id: AddressOrId, target: Address, ) -> Option>; @@ -68,25 +68,32 @@ pub trait Host { /// Sstore, calls `ContextTr::journal_mut().sstore(address, key, value)` fn sstore( &mut self, - address: Address, + address_or_id: AddressOrId, key: StorageKey, value: StorageValue, ) -> Option>; /// Sload, calls `ContextTr::journal_mut().sload(address, key)` - fn sload(&mut self, address: Address, key: StorageKey) -> Option>; + fn sload( + &mut self, + address_or_id: AddressOrId, + key: StorageKey, + ) -> Option>; /// Tstore, calls `ContextTr::journal_mut().tstore(address, key, value)` - fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue); + fn tstore(&mut self, address_or_id: AddressOrId, key: StorageKey, value: StorageValue); /// Tload, calls `ContextTr::journal_mut().tload(address, key)` - fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue; + fn tload(&mut self, address_or_id: AddressOrId, key: StorageKey) -> StorageValue; /// Balance, calls `ContextTr::journal_mut().load_account(address)` - fn balance(&mut self, address: Address) -> Option>; + fn balance(&mut self, address_or_id: AddressOrId) -> Option>; /// Load account delegated, calls `ContextTr::journal_mut().load_account_delegated(address)` - fn load_account_delegated(&mut self, address: Address) -> Option>; + fn load_account_delegated( + &mut self, + address_or_id: AddressOrId, + ) -> Option>; /// Load account code, calls `ContextTr::journal_mut().load_account_code(address)` - fn load_account_code(&mut self, address: Address) -> Option>; + fn load_account_code(&mut self, address_or_id: AddressOrId) -> Option>; /// Load account code hash, calls `ContextTr::journal_mut().code_hash(address)` - fn load_account_code_hash(&mut self, address: Address) -> Option>; + fn load_account_code_hash(&mut self, address_or_id: AddressOrId) -> Option>; } /// Dummy host that implements [`Host`] trait and returns all default values. @@ -152,7 +159,7 @@ impl Host for DummyHost { fn selfdestruct( &mut self, - _address: Address, + _address_or_id: AddressOrId, _target: Address, ) -> Option> { None @@ -162,36 +169,43 @@ impl Host for DummyHost { fn sstore( &mut self, - _address: Address, + _address_or_id: AddressOrId, _key: StorageKey, _value: StorageValue, ) -> Option> { None } - fn sload(&mut self, _address: Address, _key: StorageKey) -> Option> { + fn sload( + &mut self, + _address_or_id: AddressOrId, + _key: StorageKey, + ) -> Option> { None } - fn tstore(&mut self, _address: Address, _key: StorageKey, _value: StorageValue) {} + fn tstore(&mut self, _address_or_id: AddressOrId, _key: StorageKey, _value: StorageValue) {} - fn tload(&mut self, _address: Address, _key: StorageKey) -> StorageValue { + fn tload(&mut self, _address_or_id: AddressOrId, _key: StorageKey) -> StorageValue { StorageValue::ZERO } - fn balance(&mut self, _address: Address) -> Option> { + fn balance(&mut self, _address_or_id: AddressOrId) -> Option> { None } - fn load_account_delegated(&mut self, _address: Address) -> Option> { + fn load_account_delegated( + &mut self, + _address_or_id: AddressOrId, + ) -> Option> { None } - fn load_account_code(&mut self, _address: Address) -> Option> { + fn load_account_code(&mut self, _address_or_id: AddressOrId) -> Option> { None } - fn load_account_code_hash(&mut self, _address: Address) -> Option> { + fn load_account_code_hash(&mut self, _address_or_id: AddressOrId) -> Option> { None } } diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 9d45323f14..a4e93556b7 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -3,7 +3,8 @@ use crate::context::{SStoreResult, SelfDestructResult}; use core::ops::{Deref, DerefMut}; use database_interface::Database; use primitives::{ - hardfork::SpecId, Address, Bytes, HashSet, Log, StorageKey, StorageValue, B256, U256, + hardfork::SpecId, Address, AddressAndId, AddressOrId, Bytes, HashSet, Log, StorageKey, + StorageValue, B256, U256, }; use state::{Account, Bytecode}; use std::vec::Vec; @@ -31,23 +32,23 @@ pub trait JournalTr { /// Loads the storage from database if not found in Journal state. fn sload( &mut self, - address: Address, + address_or_id: AddressOrId, key: StorageKey, ) -> Result, ::Error>; /// Stores the storage value in Journal state. fn sstore( &mut self, - address: Address, + address_or_id: AddressOrId, key: StorageKey, value: StorageValue, ) -> Result, ::Error>; /// Loads transient storage value. - fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue; + fn tload(&mut self, address_or_id: AddressOrId, key: StorageKey) -> StorageValue; /// Stores transient storage value. - fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue); + fn tstore(&mut self, address_or_id: AddressOrId, key: StorageKey, value: StorageValue); /// Logs the log in Journal state. fn log(&mut self, log: Log); @@ -55,21 +56,24 @@ pub trait JournalTr { /// Marks the account for selfdestruction and transfers all the balance to the target. fn selfdestruct( &mut self, - address: Address, + address_or_id: AddressOrId, target: Address, ) -> Result, ::Error>; - /// Warms the account and storage. + /// Warms the account and storage. Warming of account needs address. fn warm_account_and_storage( &mut self, address: Address, storage_keys: impl IntoIterator, - ) -> Result<(), ::Error>; + ) -> Result::Error>; /// Warms the coinbase account. fn warm_coinbase_account(&mut self, address: Address); - /// Warms the precompiles. + /// Warms the precompiles. Precompile account will not be fetched from database + /// + /// Warming of precompiles assumes that account are frequently accessed and it will + /// be considered warm even when loaded from database. fn warm_precompiles(&mut self, addresses: HashSet
); /// Returns the addresses of the precompiles. @@ -78,21 +82,21 @@ pub trait JournalTr { /// Sets the spec id. fn set_spec_id(&mut self, spec_id: SpecId); - /// Touches the account. - fn touch_account(&mut self, address: Address); + /// Touches the account + fn touch_account(&mut self, address_or_id: AddressOrId); /// Transfers the balance from one account to another. fn transfer( &mut self, - from: Address, - to: Address, + from: AddressOrId, + to: AddressOrId, balance: U256, ) -> Result, ::Error>; /// Increments the balance of the account. fn caller_accounting_journal_entry( &mut self, - address: Address, + address_or_id: AddressOrId, old_balance: U256, bump_nonce: bool, ); @@ -100,72 +104,68 @@ pub trait JournalTr { /// Increments the balance of the account. fn balance_incr( &mut self, - address: Address, + address_or_id: AddressOrId, balance: U256, - ) -> Result<(), ::Error>; + ) -> Result::Error>; /// Increments the nonce of the account. - fn nonce_bump_journal_entry(&mut self, address: Address); + fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId); /// Loads the account. fn load_account( &mut self, - address: Address, - ) -> Result, ::Error>; + address_or_id: AddressOrId, + ) -> Result, ::Error>; /// Loads the account code. fn load_account_code( &mut self, - address: Address, - ) -> Result, ::Error>; + address_or_id: AddressOrId, + ) -> Result, ::Error>; /// Loads the account delegated. fn load_account_delegated( &mut self, - address: Address, + address_or_id: AddressOrId, ) -> Result, ::Error>; /// Sets bytecode with hash. Assume that account is warm. - fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256); + fn set_code_with_hash(&mut self, address_or_id: AddressOrId, code: Bytecode, hash: B256); /// Sets bytecode and calculates hash. /// /// Assume account is warm. #[inline] - fn set_code(&mut self, address: Address, code: Bytecode) { + fn set_code(&mut self, address_or_id: AddressOrId, code: Bytecode) { let hash = code.hash_slow(); - self.set_code_with_hash(address, code, hash); + self.set_code_with_hash(address_or_id, code, hash); } /// Returns account code bytes and if address is cold loaded. #[inline] fn code( &mut self, - address: Address, - ) -> Result, ::Error> { - let a = self.load_account_code(address)?; + address_or_id: AddressOrId, + ) -> Result<(StateLoad, AddressAndId), ::Error> { + let a = self.load_account_code(address_or_id)?; // SAFETY: Safe to unwrap as load_code will insert code if it is empty. - let code = a.info.code.as_ref().unwrap(); + let code = a.0.info.code.as_ref().unwrap(); let code = code.original_bytes(); - Ok(StateLoad::new(code, a.is_cold)) + Ok((StateLoad::new(code, a.is_cold), a.1)) } /// Gets code hash of account. fn code_hash( &mut self, - address: Address, - ) -> Result, ::Error> { - let acc = self.load_account_code(address)?; - if acc.is_empty() { - return Ok(StateLoad::new(B256::ZERO, acc.is_cold)); + address_or_id: AddressOrId, + ) -> Result<(StateLoad, AddressAndId), ::Error> { + let acc = self.load_account_code(address_or_id)?; + if acc.0.is_empty() { + return Ok((StateLoad::new(B256::ZERO, acc.is_cold), acc.1)); } - // SAFETY: Safe to unwrap as load_code will insert code if it is empty. - let _code = acc.info.code.as_ref().unwrap(); - - let hash = acc.info.code_hash; - - Ok(StateLoad::new(hash, acc.is_cold)) + let hash = acc.0.info.code_hash; + Ok((StateLoad::new(hash, acc.is_cold), acc.1)) } /// Called at the end of the transaction to clean all residue data from journal. @@ -186,8 +186,8 @@ pub trait JournalTr { /// Creates a checkpoint of the account creation. fn create_account_checkpoint( &mut self, - caller: Address, - address: Address, + caller_or_id: AddressOrId, + address_or_id: AddressOrId, balance: U256, spec_id: SpecId, ) -> Result; @@ -281,4 +281,8 @@ pub struct AccountLoad { pub is_delegate_account_cold: Option, /// Is account empty, if `true` account is not created pub is_empty: bool, + /// Account address and id. + pub address_and_id: AddressAndId, + /// delegated account address, + pub delegated_account_address: Option>, } diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 9bbf417be1..fb533b3a13 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -7,7 +7,10 @@ use context_interface::{ }; use database_interface::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}; use derive_where::derive_where; -use primitives::{hardfork::SpecId, Address, Bytes, Log, StorageKey, StorageValue, B256, U256}; +use primitives::{ + hardfork::SpecId, Address, AddressAndId, AddressOrId, Bytes, Log, StorageKey, StorageValue, + B256, U256, +}; /// EVM context contains data that EVM needs for execution. #[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, JOURNAL, ::Error, LOCAL)] @@ -530,9 +533,12 @@ impl< /* Journal */ - fn load_account_delegated(&mut self, address: Address) -> Option> { + fn load_account_delegated( + &mut self, + address_or_id: AddressOrId, + ) -> Option> { self.journal_mut() - .load_account_delegated(address) + .load_account_delegated(address_or_id) .map_err(|e| { *self.error() = Err(e.into()); }) @@ -540,10 +546,10 @@ impl< } /// Gets balance of `address` and if the account is cold. - fn balance(&mut self, address: Address) -> Option> { + fn balance(&mut self, address_or_id: AddressOrId) -> Option> { self.journal_mut() - .load_account(address) - .map(|acc| acc.map(|a| a.info.balance)) + .load_account(address_or_id) + .map(|acc| acc.map(|a| a.0.info.balance)) .map_err(|e| { *self.error() = Err(e.into()); }) @@ -551,27 +557,33 @@ impl< } /// Gets code of `address` and if the account is cold. - fn load_account_code(&mut self, address: Address) -> Option> { + fn load_account_code(&mut self, address_or_id: AddressOrId) -> Option> { self.journal_mut() - .code(address) + .code(address_or_id) .map_err(|e| { *self.error() = Err(e.into()); }) .ok() + .map(|(a, _)| a) } /// Gets code hash of `address` and if the account is cold. - fn load_account_code_hash(&mut self, address: Address) -> Option> { + fn load_account_code_hash(&mut self, address_or_id: AddressOrId) -> Option> { self.journal_mut() - .code_hash(address) + .code_hash(address_or_id) .map_err(|e| { *self.error() = Err(e.into()); }) .ok() + .map(|(a, _)| a) } /// Gets storage value of `address` at `index` and if the account is cold. - fn sload(&mut self, address: Address, index: StorageKey) -> Option> { + fn sload( + &mut self, + address: AddressOrId, + index: StorageKey, + ) -> Option> { self.journal_mut() .sload(address, index) .map_err(|e| { @@ -585,7 +597,7 @@ impl< /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value. fn sstore( &mut self, - address: Address, + address: AddressOrId, index: StorageKey, value: StorageValue, ) -> Option> { @@ -598,12 +610,12 @@ impl< } /// Gets the transient storage value of `address` at `index`. - fn tload(&mut self, address: Address, index: StorageKey) -> StorageValue { + fn tload(&mut self, address: AddressOrId, index: StorageKey) -> StorageValue { self.journal_mut().tload(address, index) } /// Sets the transient storage value of `address` at `index`. - fn tstore(&mut self, address: Address, index: StorageKey, value: StorageValue) { + fn tstore(&mut self, address: AddressOrId, index: StorageKey, value: StorageValue) { self.journal_mut().tstore(address, index, value) } @@ -615,7 +627,7 @@ impl< /// Marks `address` to be deleted, with funds transferred to `target`. fn selfdestruct( &mut self, - address: Address, + address: AddressOrId, target: Address, ) -> Option> { self.journal_mut() diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 206abbb4e8..a1682e322b 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -16,7 +16,10 @@ use context_interface::{ }; use core::ops::{Deref, DerefMut}; use database_interface::Database; -use primitives::{hardfork::SpecId, Address, HashSet, Log, StorageKey, StorageValue, B256, U256}; +use primitives::{ + hardfork::SpecId, Address, AddressAndId, AddressOrId, HashSet, Log, StorageKey, StorageValue, + B256, U256, +}; use state::{Account, EvmState}; use std::vec::Vec; @@ -106,27 +109,28 @@ impl JournalTr for Journal { fn sload( &mut self, - address: Address, + address_or_id: AddressOrId, key: StorageKey, ) -> Result, ::Error> { - self.inner.sload(&mut self.database, address, key) + self.inner.sload(&mut self.database, address_or_id, key) } fn sstore( &mut self, - address: Address, + address_or_id: AddressOrId, key: StorageKey, value: StorageValue, ) -> Result, ::Error> { - self.inner.sstore(&mut self.database, address, key, value) + self.inner + .sstore(&mut self.database, address_or_id, key, value) } - fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue { - self.inner.tload(address, key) + fn tload(&mut self, address_or_id: AddressOrId, key: StorageKey) -> StorageValue { + self.inner.tload(address_or_id, key) } - fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue) { - self.inner.tstore(address, key, value) + fn tstore(&mut self, address_or_id: AddressOrId, key: StorageKey, value: StorageValue) { + self.inner.tstore(address_or_id, key, value) } fn log(&mut self, log: Log) { @@ -135,10 +139,11 @@ impl JournalTr for Journal { fn selfdestruct( &mut self, - address: Address, + address_or_id: AddressOrId, target: Address, ) -> Result, DB::Error> { - self.inner.selfdestruct(&mut self.database, address, target) + self.inner + .selfdestruct(&mut self.database, address_or_id, target) } fn warm_coinbase_account(&mut self, address: Address) { @@ -167,10 +172,15 @@ impl JournalTr for Journal { &mut self, address: Address, storage_keys: impl IntoIterator, - ) -> Result<(), ::Error> { + ) -> Result::Error> { self.inner - .load_account_optional(&mut self.database, address, false, storage_keys)?; - Ok(()) + .load_account_optional( + &mut self.database, + AddressOrId::Address(address), + false, + storage_keys, + ) + .map(|i| i.1) } #[inline] @@ -181,66 +191,69 @@ impl JournalTr for Journal { #[inline] fn transfer( &mut self, - from: Address, - to: Address, + from: AddressOrId, + to: AddressOrId, balance: U256, ) -> Result, DB::Error> { self.inner.transfer(&mut self.database, from, to, balance) } #[inline] - fn touch_account(&mut self, address: Address) { - self.inner.touch(address); + fn touch_account(&mut self, address_or_id: AddressOrId) { + self.inner.touch(&address_or_id); } #[inline] fn caller_accounting_journal_entry( &mut self, - address: Address, + address_or_id: AddressOrId, old_balance: U256, bump_nonce: bool, ) { self.inner - .caller_accounting_journal_entry(address, old_balance, bump_nonce); + .caller_accounting_journal_entry(address_or_id, old_balance, bump_nonce); } /// Increments the balance of the account. #[inline] fn balance_incr( &mut self, - address: Address, + address_or_id: AddressOrId, balance: U256, - ) -> Result<(), ::Error> { + ) -> Result::Error> { self.inner - .balance_incr(&mut self.database, address, balance) + .balance_incr(&mut self.database, address_or_id, balance) } /// Increments the nonce of the account. #[inline] - fn nonce_bump_journal_entry(&mut self, address: Address) { - self.inner.nonce_bump_journal_entry(address) + fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId) { + self.inner.nonce_bump_journal_entry(address_or_id) } #[inline] - fn load_account(&mut self, address: Address) -> Result, DB::Error> { - self.inner.load_account(&mut self.database, address) + fn load_account( + &mut self, + address_or_id: AddressOrId, + ) -> Result, DB::Error> { + self.inner.load_account(&mut self.database, address_or_id) } #[inline] fn load_account_code( &mut self, - address: Address, - ) -> Result, DB::Error> { - self.inner.load_code(&mut self.database, address) + address_or_id: AddressOrId, + ) -> Result, DB::Error> { + self.inner.load_code(&mut self.database, address_or_id) } #[inline] fn load_account_delegated( &mut self, - address: Address, + address_or_id: AddressOrId, ) -> Result, DB::Error> { self.inner - .load_account_delegated(&mut self.database, address) + .load_account_delegated(&mut self.database, address_or_id) } #[inline] @@ -259,21 +272,21 @@ impl JournalTr for Journal { } #[inline] - fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) { - self.inner.set_code_with_hash(address, code, hash); + fn set_code_with_hash(&mut self, address_or_id: AddressOrId, code: Bytecode, hash: B256) { + self.inner.set_code_with_hash(address_or_id, code, hash); } #[inline] fn create_account_checkpoint( &mut self, - caller: Address, - address: Address, + caller_or_id: AddressOrId, + target_or_id: AddressOrId, balance: U256, spec_id: SpecId, ) -> Result { // Ignore error. self.inner - .create_account_checkpoint(caller, address, balance, spec_id) + .create_account_checkpoint(caller_or_id, target_or_id, balance, spec_id) } #[inline] diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 99eaa19546..5e71412469 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -299,7 +299,7 @@ impl JournalInner { db: &mut DB, address_or_id: AddressOrId, balance: U256, - ) -> Result<(), DB::Error> { + ) -> Result { let (account, address) = self.load_account(db, address_or_id)?.data; let old_balance = account.info.balance; account.info.balance = account.info.balance.saturating_add(balance); @@ -313,7 +313,7 @@ impl JournalInner { // add journal entry for balance increment. self.journal .push(ENTRY::balance_changed(address.id(), old_balance)); - Ok(()) + Ok(address) } /// Increments the nonce of the account. @@ -387,8 +387,8 @@ impl JournalInner { #[inline] pub fn create_account_checkpoint( &mut self, - caller: AddressOrId, - target_address: Address, + caller_or_id: AddressOrId, + target_or_id: AddressOrId, balance: U256, spec_id: SpecId, ) -> Result { @@ -396,7 +396,7 @@ impl JournalInner { let checkpoint = self.checkpoint(); // Fetch balance of caller. - let (caller_acc, caller) = self.state_new.get(&caller).unwrap(); + let (caller_acc, caller) = self.state_new.get(&caller_or_id).unwrap(); let caller_balance = caller_acc.info.balance; // Check if caller has enough balance to send to the created contract. if caller_balance < balance { @@ -405,10 +405,7 @@ impl JournalInner { } // Newly created account is present, as we just loaded it. - let (target_acc, target) = self - .state_new - .get_mut(&AddressOrId::Address(target_address)) - .unwrap(); + let (target_acc, target) = self.state_new.get_mut(&target_or_id).unwrap(); let last_journal = &mut self.journal; // New account can be created if: @@ -606,6 +603,8 @@ impl JournalInner { let mut account_load = StateLoad::new( AccountLoad { + address_and_id: account.1, + delegated_account_address: None, is_delegate_account_cold: None, is_empty, }, @@ -647,8 +646,8 @@ impl JournalInner { storage_keys: impl IntoIterator, ) -> Result, DB::Error> { todo!(); - let load = Default::default(); - let id = AddressAndId::new(address_or_id.address().unwrap(), 0); + //let load = Default::default(); + //let id = AddressAndId::new(address_or_id.address().unwrap(), 0); // let load = match self.state.entry(address) { // Entry::Occupied(entry) => { // let account = entry.into_mut(); @@ -687,32 +686,32 @@ impl JournalInner { // }; // journal loading of cold account. - if load.is_cold { - self.journal.push(ENTRY::account_warmed(id.id())); - } - if load_code { - let info = &mut load.data.info; - if info.code.is_none() { - let code = if info.code_hash == KECCAK_EMPTY { - Bytecode::default() - } else { - db.code_by_hash(info.code_hash)? - }; - info.code = Some(code); - } - } - - for storage_key in storage_keys.into_iter() { - sload_with_account( - load.data, - db, - &mut self.journal, - self.transaction_id, - id, - storage_key, - )?; - } - Ok((load, id)) + // if load.is_cold { + // self.journal.push(ENTRY::account_warmed(id.id())); + // } + // if load_code { + // let info = &mut load.data.info; + // if info.code.is_none() { + // let code = if info.code_hash == KECCAK_EMPTY { + // Bytecode::default() + // } else { + // db.code_by_hash(info.code_hash)? + // }; + // info.code = Some(code); + // } + // } + + // for storage_key in storage_keys.into_iter() { + // sload_with_account( + // load.data, + // db, + // &mut self.journal, + // self.transaction_id, + // id, + // storage_key, + // )?; + // } + // Ok((load, id)) } /// Loads storage slot. diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 823ec568df..a73317d821 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -25,7 +25,7 @@ use primitives::{ constants::CALL_STACK_LIMIT, hardfork::SpecId::{self, HOMESTEAD, LONDON, SPURIOUS_DRAGON}, }; -use primitives::{keccak256, Address, Bytes, U256}; +use primitives::{keccak256, Address, AddressAndId, Bytes, U256}; use state::Bytecode; use std::borrow::ToOwned; use std::boxed::Box; @@ -165,7 +165,7 @@ impl EthFrame { // Make account warm and loaded. let _ = ctx .journal_mut() - .load_account_delegated(inputs.bytecode_address)?; + .load_account_delegated(inputs.bytecode_address.to_id())?; // Create subroutine checkpoint let checkpoint = ctx.journal_mut().checkpoint(); @@ -174,10 +174,11 @@ impl EthFrame { if let CallValue::Transfer(value) = inputs.value { // Transfer value from caller to called account // Target will get touched even if balance transferred is zero. - if let Some(i) = - ctx.journal_mut() - .transfer(inputs.caller, inputs.target_address, value)? - { + if let Some(i) = ctx.journal_mut().transfer( + inputs.caller.to_id(), + inputs.target_address.to_id(), + value, + )? { ctx.journal_mut().checkpoint_revert(checkpoint); return return_result(i.into()); } @@ -196,7 +197,7 @@ impl EthFrame { if let Some(result) = precompiles .run( ctx, - &inputs.bytecode_address, + &inputs.bytecode_address.address(), &interpreter_input, is_static, gas_limit, @@ -216,15 +217,16 @@ impl EthFrame { let account = ctx .journal_mut() - .load_account_code(inputs.bytecode_address)?; + .load_account_code(inputs.bytecode_address.to_id())?; - let mut code_hash = account.info.code_hash(); - let mut bytecode = account.info.code.clone().unwrap_or_default(); + let mut code_hash = account.0.info.code_hash(); + let mut bytecode = account.0.info.code.clone().unwrap_or_default(); if let Bytecode::Eip7702(eip7702_bytecode) = bytecode { let account = &ctx .journal_mut() - .load_account_code(eip7702_bytecode.delegated_address)? + .load_account_code(eip7702_bytecode.delegated_address.into())? + .0 .info; bytecode = account.code.clone().unwrap_or_default(); code_hash = account.code_hash(); @@ -254,6 +256,49 @@ impl EthFrame { Ok(ItemOrResult::Item(this.consume())) } + /* + + + instruction CALL: + I want to set all fields that interpreter is going to use? + // Should i used InputsImpl, probably yes? + + Additionally i needs some specific data for Call info + + Call specific are: + return_memory_offset + scheme + is_static + + Create specific: + Scheme + init_code can be data + + CallInput: + InputsImpl + + + FrameInput: + Interpreter `Inputs for FrameInput` + + FrameOutput: + InterpResult + scheme: + return_mem: + address: + + + CreateInput: + InputsImpl: + + + What do I want? + To consolidate Inputs and CallInput CreateInput. + + + + */ + /// Make create frame. #[inline] pub fn make_create_frame< @@ -283,14 +328,12 @@ impl EthFrame { return return_error(InstructionResult::CallTooDeep); } - // Prague EOF - // TODO(EOF) - // if spec.is_enabled_in(OSAKA) && inputs.init_code.starts_with(&EOF_MAGIC_BYTES) { - // return return_error(InstructionResult::CreateInitCodeStartingEF00); - // } - // Fetch balance of caller. - let caller_info = &mut context.journal_mut().load_account(inputs.caller)?.data.info; + let caller_info = &mut context + .journal_mut() + .load_account(inputs.caller.to_id())? + .0 + .info; // Check if caller has enough balance to send to the created contract. if caller_info.balance < inputs.value { @@ -305,26 +348,32 @@ impl EthFrame { caller_info.nonce = new_nonce; context .journal_mut() - .nonce_bump_journal_entry(inputs.caller); + .nonce_bump_journal_entry(inputs.caller.to_id()); // Create address let mut init_code_hash = None; let created_address = match inputs.scheme { - CreateScheme::Create => inputs.caller.create(old_nonce), + CreateScheme::Create => inputs.caller.address().create(old_nonce), CreateScheme::Create2 { salt } => { let init_code_hash = *init_code_hash.insert(keccak256(&inputs.init_code)); - inputs.caller.create2(salt.to_be_bytes(), init_code_hash) + inputs + .caller + .address() + .create2(salt.to_be_bytes(), init_code_hash) } CreateScheme::Custom { address } => address, }; // warm load account. - context.journal_mut().load_account(created_address)?; + let created_address = context + .journal_mut() + .load_account(created_address.into())? + .1; // Create account, transfer funds and make the journal checkpoint. let checkpoint = match context.journal_mut().create_account_checkpoint( - inputs.caller, - created_address, + inputs.caller.to_id(), + created_address.to_id(), inputs.value, spec, ) { @@ -347,7 +396,7 @@ impl EthFrame { let gas_limit = inputs.gas_limit; this.get(EthFrame::invalid).clear( - FrameData::Create(CreateFrame { created_address }), + FrameData::new_create(created_address), FrameInput::Create(inputs), depth, memory, @@ -552,7 +601,7 @@ pub fn return_create( journal: &mut JOURNAL, checkpoint: JournalCheckpoint, interpreter_result: &mut InterpreterResult, - address: Address, + address: AddressAndId, max_code_size: usize, is_eip3541_disabled: bool, spec_id: SpecId, diff --git a/crates/handler/src/frame_data.rs b/crates/handler/src/frame_data.rs index 2c1d6b5243..691b574cb6 100644 --- a/crates/handler/src/frame_data.rs +++ b/crates/handler/src/frame_data.rs @@ -1,7 +1,7 @@ use context_interface::result::Output; use core::ops::Range; use interpreter::{CallOutcome, CreateOutcome, Gas, InstructionResult, InterpreterResult}; -use primitives::Address; +use primitives::{Address, AddressAndId}; /// Call Frame #[derive(Debug, Clone)] @@ -16,7 +16,7 @@ pub struct CallFrame { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateFrame { /// Create frame has a created address. - pub created_address: Address, + pub created_address: AddressAndId, } /// Frame Data @@ -107,7 +107,7 @@ impl FrameResult { impl FrameData { /// Creates a new create frame data. - pub fn new_create(created_address: Address) -> Self { + pub fn new_create(created_address: AddressAndId) -> Self { Self::Create(CreateFrame { created_address }) } @@ -129,7 +129,7 @@ impl FrameData { } /// Returns created address if frame is create otherwise returns None. - pub fn created_address(&self) -> Option
{ + pub fn created_address(&self) -> Option { match self { Self::Create(create_frame) => Some(create_frame.created_address), _ => None, diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 731fb1e50b..53cd798364 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -11,7 +11,7 @@ use crate::{ InterpreterAction, }; use context_interface::CreateScheme; -use primitives::{hardfork::SpecId, Address, Bytes, B256, U256}; +use primitives::{hardfork::SpecId, AddressOrId, Bytes, U256}; use std::boxed::Box; use crate::InstructionContext; @@ -107,7 +107,7 @@ pub fn create( /// Message call with value transfer to another account. pub fn call(context: InstructionContext<'_, H, WIRE>) { popn!([local_gas_limit, to, value], context.interpreter); - let to = to.into_address(); + let to = to.into_address().into(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -124,12 +124,16 @@ pub fn call(context: InstructionContex return; }; - let Some(account_load) = context.host.load_account_delegated(to) else { + let Some(account_load) = context + .host + .load_account_delegated(AddressOrId::Address(to)) + else { context .interpreter .halt(InstructionResult::FatalExternalError); return; }; + let to = account_load.address_and_id; let Some(mut gas_limit) = calc_call_gas( context.interpreter, @@ -173,7 +177,7 @@ pub fn call_code( context: InstructionContext<'_, H, WIRE>, ) { popn!([local_gas_limit, to, value], context.interpreter); - let to = Address::from_word(B256::from(to)); + let to = to.into_address().into(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -189,6 +193,7 @@ pub fn call_code( .halt(InstructionResult::FatalExternalError); return; }; + let to = load.address_and_id; // Set `is_empty` to false as we are not creating this account. load.is_empty = false; @@ -232,7 +237,7 @@ pub fn delegate_call( ) { check!(context.interpreter, HOMESTEAD); popn!([local_gas_limit, to], context.interpreter); - let to = Address::from_word(B256::from(to)); + let to = to.into_address().into(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -247,6 +252,7 @@ pub fn delegate_call( .halt(InstructionResult::FatalExternalError); return; }; + let to = load.address_and_id; // Set is_empty to false as we are not creating this account. load.is_empty = false; @@ -283,7 +289,7 @@ pub fn static_call( ) { check!(context.interpreter, BYZANTIUM); popn!([local_gas_limit, to], context.interpreter); - let to = Address::from_word(B256::from(to)); + let to = to.into_address().into(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -298,6 +304,8 @@ pub fn static_call( .halt(InstructionResult::FatalExternalError); return; }; + let to = load.address_and_id; + // Set `is_empty` to false as we are not creating this account. load.is_empty = false; let Some(gas_limit) = calc_call_gas(context.interpreter, load, false, local_gas_limit) else { diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 4fb362e7a9..5e5d4accf6 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -14,7 +14,7 @@ use crate::InstructionContext; /// Gets the balance of the given account. pub fn balance(context: InstructionContext<'_, H, WIRE>) { popn_top!([], top, context.interpreter); - let address = top.into_address(); + let address = top.into_address().into(); let Some(balance) = context.host.balance(address) else { context .interpreter @@ -47,7 +47,7 @@ pub fn selfbalance( let Some(balance) = context .host - .balance(context.interpreter.input.target_address()) + .balance(context.interpreter.input.target_address().to_id()) else { context .interpreter @@ -64,7 +64,7 @@ pub fn extcodesize( context: InstructionContext<'_, H, WIRE>, ) { popn_top!([], top, context.interpreter); - let address = top.into_address(); + let address = top.into_address().into(); let Some(code) = context.host.load_account_code(address) else { context .interpreter @@ -89,7 +89,7 @@ pub fn extcodehash( ) { check!(context.interpreter, CONSTANTINOPLE); popn_top!([], top, context.interpreter); - let address = top.into_address(); + let address = top.into_address().into(); let Some(code_hash) = context.host.load_account_code_hash(address) else { context .interpreter @@ -117,7 +117,7 @@ pub fn extcodecopy( [address, memory_offset, code_offset, len_u256], context.interpreter ); - let address = address.into_address(); + let address = address.into_address().into(); let Some(code) = context.host.load_account_code(address) else { context .interpreter @@ -194,7 +194,7 @@ pub fn sload(context: InstructionConte let Some(value) = context .host - .sload(context.interpreter.input.target_address(), *index) + .sload(context.interpreter.input.target_address().to_id(), *index) else { context .interpreter @@ -217,11 +217,11 @@ pub fn sstore(context: InstructionCont popn!([index, value], context.interpreter); - let Some(state_load) = - context - .host - .sstore(context.interpreter.input.target_address(), index, value) - else { + let Some(state_load) = context.host.sstore( + context.interpreter.input.target_address().to_id(), + index, + value, + ) else { context .interpreter .halt(InstructionResult::FatalExternalError); @@ -265,9 +265,11 @@ pub fn tstore(context: InstructionCont popn!([index, value], context.interpreter); - context - .host - .tstore(context.interpreter.input.target_address(), index, value); + context.host.tstore( + context.interpreter.input.target_address().to_id(), + index, + value, + ); } /// EIP-1153: Transient storage opcodes @@ -280,7 +282,7 @@ pub fn tload(context: InstructionConte *index = context .host - .tload(context.interpreter.input.target_address(), *index); + .tload(context.interpreter.input.target_address().to_id(), *index); } /// Implements the LOG0-LOG4 instructions. @@ -311,7 +313,7 @@ pub fn log( }; let log = Log { - address: context.interpreter.input.target_address(), + address: *context.interpreter.input.target_address().address(), data: LogData::new(topics.into_iter().map(B256::from).collect(), data) .expect("LogData should have <=4 topics"), }; @@ -331,7 +333,7 @@ pub fn selfdestruct( let Some(res) = context .host - .selfdestruct(context.interpreter.input.target_address(), target) + .selfdestruct(context.interpreter.input.target_address().to_id(), target) else { context .interpreter diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 0bea684e7f..710e426b77 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -39,6 +39,7 @@ pub fn address(context: InstructionContext<'_ .interpreter .input .target_address() + .address() .into_word() .into() ); @@ -55,6 +56,7 @@ pub fn caller(context: InstructionContext<'_, .interpreter .input .caller_address() + .address() .into_word() .into() ); diff --git a/crates/interpreter/src/instructions/utility.rs b/crates/interpreter/src/instructions/utility.rs index 8a51ce9575..20e6109377 100644 --- a/crates/interpreter/src/instructions/utility.rs +++ b/crates/interpreter/src/instructions/utility.rs @@ -18,7 +18,7 @@ impl IntoU256 for B256 { } } -/// Trait for converting types into Address values. +/// Trait for converting types into Address values. It ingnores excess bytes. pub trait IntoAddress { /// Converts the implementing type into an Address value. fn into_address(self) -> Address; diff --git a/crates/interpreter/src/interpreter/input.rs b/crates/interpreter/src/interpreter/input.rs index fb28c8252b..f4cf81da71 100644 --- a/crates/interpreter/src/interpreter/input.rs +++ b/crates/interpreter/src/interpreter/input.rs @@ -1,5 +1,5 @@ use crate::{interpreter_types::InputsTr, CallInput}; -use primitives::{Address, U256}; +use primitives::{AddressAndId, U256}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -8,12 +8,12 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct InputsImpl { /// Storage of this account address is being used. - pub target_address: Address, + pub target_address: AddressAndId, /// Address of the bytecode that is being executed. This field is not used inside Interpreter but it is used /// by dependent projects that would need to know the address of the bytecode. - pub bytecode_address: Option
, + pub bytecode_address: Option, /// Address of the caller of the call. - pub caller_address: Address, + pub caller_address: AddressAndId, /// Input data for the call. pub input: CallInput, /// Value of the call. @@ -21,15 +21,15 @@ pub struct InputsImpl { } impl InputsTr for InputsImpl { - fn target_address(&self) -> Address { + fn target_address(&self) -> AddressAndId { self.target_address } - fn caller_address(&self) -> Address { + fn caller_address(&self) -> AddressAndId { self.caller_address } - fn bytecode_address(&self) -> Option<&Address> { + fn bytecode_address(&self) -> Option<&AddressAndId> { self.bytecode_address.as_ref() } diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index 11865c818f..eaff6c02e3 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -1,6 +1,6 @@ use context_interface::{ContextTr, LocalContextTr}; use core::ops::Range; -use primitives::{Address, Bytes, U256}; +use primitives::{AddressAndId, Bytes, U256}; /// Input enum for a call. /// /// As CallInput uses shared memory buffer it can get overridden if not used directly when call happens. @@ -77,15 +77,15 @@ pub struct CallInputs { /// The account address of bytecode that is going to be executed. /// /// Previously `context.code_address`. - pub bytecode_address: Address, + pub bytecode_address: AddressAndId, /// Target address, this account storage is going to be modified. /// /// Previously `context.address`. - pub target_address: Address, + pub target_address: AddressAndId, /// This caller is invoking the call. /// /// Previously `context.caller`. - pub caller: Address, + pub caller: AddressAndId, /// Call value. /// /// **Note**: This value may not necessarily be transferred from caller to callee, see [`CallValue`]. @@ -127,7 +127,7 @@ impl CallInputs { /// /// This is only meaningful if `transfers_value` is `true`. #[inline] - pub const fn transfer_from(&self) -> Address { + pub const fn transfer_from(&self) -> AddressAndId { self.caller } @@ -135,7 +135,7 @@ impl CallInputs { /// /// This is only meaningful if `transfers_value` is `true`. #[inline] - pub const fn transfer_to(&self) -> Address { + pub const fn transfer_to(&self) -> AddressAndId { self.target_address } diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index d44ed3eac8..b846e32bbf 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -1,12 +1,12 @@ use context_interface::CreateScheme; -use primitives::{Address, Bytes, U256}; +use primitives::{Address, AddressAndId, Bytes, U256}; /// Inputs for a create call #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateInputs { /// Caller address of the EVM - pub caller: Address, + pub caller: AddressAndId, /// The create scheme pub scheme: CreateScheme, /// The value to transfer @@ -21,9 +21,10 @@ impl CreateInputs { /// Returns the address that this create call will create. pub fn created_address(&self, nonce: u64) -> Address { match self.scheme { - CreateScheme::Create => self.caller.create(nonce), + CreateScheme::Create => self.caller.address().create(nonce), CreateScheme::Create2 { salt } => self .caller + .address() .create2_from_code(salt.to_be_bytes(), &self.init_code), CreateScheme::Custom { address } => address, } diff --git a/crates/interpreter/src/interpreter_types.rs b/crates/interpreter/src/interpreter_types.rs index 4c152336a3..a31901c907 100644 --- a/crates/interpreter/src/interpreter_types.rs +++ b/crates/interpreter/src/interpreter_types.rs @@ -1,6 +1,7 @@ use crate::{CallInput, InstructionResult, InterpreterAction}; use core::cell::Ref; use core::ops::{Deref, Range}; +use primitives::AddressAndId; use primitives::{hardfork::SpecId, Address, Bytes, B256, U256}; /// Helper function to read immediates data from the bytecode @@ -40,12 +41,12 @@ pub trait Immediates { /// Trait for fetching inputs of the call. pub trait InputsTr { /// Returns target address of the call. - fn target_address(&self) -> Address; + fn target_address(&self) -> AddressAndId; /// Returns bytecode address of the call. For DELEGATECALL this address will be different from target address. /// And if initcode is called this address will be [`None`]. - fn bytecode_address(&self) -> Option<&Address>; + fn bytecode_address(&self) -> Option<&AddressAndId>; /// Returns caller address of the call. - fn caller_address(&self) -> Address; + fn caller_address(&self) -> AddressAndId; /// Returns input of the call. fn input(&self) -> &CallInput; /// Returns call value of the call. diff --git a/crates/primitives/src/address.rs b/crates/primitives/src/address.rs index c79ebe0431..d6145a4c2a 100644 --- a/crates/primitives/src/address.rs +++ b/crates/primitives/src/address.rs @@ -14,6 +14,18 @@ pub enum AddressOrId { Id(AccountId), } +impl From
for AddressOrId { + fn from(address: Address) -> Self { + Self::Address(address) + } +} + +impl From for AddressOrId { + fn from(id: AccountId) -> Self { + Self::Id(id) + } +} + impl Default for AddressOrId { fn default() -> Self { Self::Address(Address::default()) @@ -55,13 +67,13 @@ impl AddressOrId { } /// Address and id. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AddressAndId { /// Address. - pub address: Address, + address: Address, /// Id. - pub id: AccountId, + id: AccountId, } impl AddressAndId { @@ -82,16 +94,32 @@ impl AddressAndId { pub fn id(&self) -> AccountId { self.id } + + /// Converts the address and id to an id. + pub fn to_id(&self) -> AddressOrId { + AddressOrId::Id(self.id) + } + + /// Converts the address and id to an address or id. + pub fn to_address(&self) -> AddressOrId { + AddressOrId::Address(self.address) + } } /// Address and optional id. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AddressAndOptionalId { /// Address. - pub address: Address, + address: Address, /// Id. - pub id: Option, + id: Option, +} + +impl From
for AddressAndOptionalId { + fn from(address: Address) -> Self { + Self { address, id: None } + } } impl AddressAndOptionalId { From 43232cbb732bbb59e1e04071f7e9b35ae9cad6dd Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 8 Aug 2025 16:15:58 +0200 Subject: [PATCH 03/37] continued transition work --- crates/handler/src/frame.rs | 13 +++++++++---- crates/handler/src/frame_data.rs | 9 +++++---- crates/handler/src/post_execution.rs | 6 ++++-- crates/handler/src/pre_execution.rs | 7 ++++--- .../src/interpreter_action/create_outcome.rs | 6 +++--- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index a73317d821..1eb0ab3745 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -1,7 +1,7 @@ use crate::evm::FrameTr; use crate::item_or_result::FrameInitOrResult; use crate::{precompile_provider::PrecompileProvider, ItemOrResult}; -use crate::{CallFrame, CreateFrame, FrameData, FrameResult}; +use crate::{CallFrame, FrameData, FrameResult}; use context::result::FromStringError; use context_interface::context::ContextError; use context_interface::local::{FrameToken, OutFrame}; @@ -25,7 +25,7 @@ use primitives::{ constants::CALL_STACK_LIMIT, hardfork::SpecId::{self, HOMESTEAD, LONDON, SPURIOUS_DRAGON}, }; -use primitives::{keccak256, Address, AddressAndId, Bytes, U256}; +use primitives::{keccak256, AddressAndId, Bytes, U256}; use state::Bytecode; use std::borrow::ToOwned; use std::boxed::Box; @@ -582,7 +582,12 @@ impl EthFrame { let stack_item = if instruction_result.is_ok() { this_gas.record_refund(outcome.gas().refunded()); - outcome.address.unwrap_or_default().into_word().into() + outcome + .address + .unwrap_or_default() + .address() + .into_word() + .into() } else { U256::ZERO }; @@ -652,7 +657,7 @@ pub fn return_create( let bytecode = Bytecode::new_legacy(interpreter_result.output.clone()); // Set code - journal.set_code(address, bytecode); + journal.set_code(address.to_id(), bytecode); interpreter_result.result = InstructionResult::Return; } diff --git a/crates/handler/src/frame_data.rs b/crates/handler/src/frame_data.rs index 691b574cb6..9e72875252 100644 --- a/crates/handler/src/frame_data.rs +++ b/crates/handler/src/frame_data.rs @@ -1,7 +1,7 @@ use context_interface::result::Output; use core::ops::Range; use interpreter::{CallOutcome, CreateOutcome, Gas, InstructionResult, InterpreterResult}; -use primitives::{Address, AddressAndId}; +use primitives::AddressAndId; /// Call Frame #[derive(Debug, Clone)] @@ -56,9 +56,10 @@ impl FrameResult { pub fn output(&self) -> Output { match self { FrameResult::Call(outcome) => Output::Call(outcome.result.output.clone()), - FrameResult::Create(outcome) => { - Output::Create(outcome.result.output.clone(), outcome.address) - } + FrameResult::Create(outcome) => Output::Create( + outcome.result.output.clone(), + outcome.address.map(|address| *address.address()), + ), } } diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index 69f5d453f3..ca8f1aff69 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -35,7 +35,8 @@ pub fn reimburse_caller( additional_refund: U256, ) -> Result<(), ::Error> { let basefee = context.block().basefee() as u128; - let caller = context.tx().caller(); + // TODO save AccountId somewhere so we can access it here. + let caller = context.tx().caller().into(); let effective_gas_price = context.tx().effective_gas_price(basefee); // Return balance of not spend gas. @@ -55,7 +56,8 @@ pub fn reward_beneficiary( context: &mut CTX, gas: &Gas, ) -> Result<(), ::Error> { - let beneficiary = context.block().beneficiary(); + // TODO save beneficiary AccountId somewhere so we can access it here. + let beneficiary = context.block().beneficiary().into(); let basefee = context.block().basefee() as u128; let effective_gas_price = context.tx().effective_gas_price(basefee); diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 0c9bf87b9e..8a5b9715a5 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -123,7 +123,8 @@ pub fn validate_against_state_and_deduct_caller< let (tx, journal) = context.tx_journal_mut(); // Load caller's account. - let caller_account = journal.load_account_code(tx.caller())?.data; + // TODO load account, obtains AccountId and store it somewhere so we can access later. + let (caller_account, caller) = journal.load_account_code(tx.caller().into())?.data; validate_account_nonce_and_code( &mut caller_account.info, @@ -172,7 +173,7 @@ pub fn validate_against_state_and_deduct_caller< caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } - journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); + journal.caller_accounting_journal_entry(caller.to_id(), old_balance, tx.kind().is_call()); Ok(()) } @@ -214,7 +215,7 @@ pub fn apply_eip7702_auth_list< // warm authority account and check nonce. // 4. Add `authority` to `accessed_addresses` (as defined in [EIP-2929](./eip-2929.md).) - let mut authority_acc = journal.load_account_code(authority)?; + let authority_acc = journal.load_account_code(authority.into())?.data.0; // 5. Verify the code of `authority` is either empty or already delegated. if let Some(bytecode) = &authority_acc.info.code { diff --git a/crates/interpreter/src/interpreter_action/create_outcome.rs b/crates/interpreter/src/interpreter_action/create_outcome.rs index 11d7204e66..3848206323 100644 --- a/crates/interpreter/src/interpreter_action/create_outcome.rs +++ b/crates/interpreter/src/interpreter_action/create_outcome.rs @@ -1,5 +1,5 @@ use crate::{Gas, InstructionResult, InterpreterResult}; -use primitives::{Address, Bytes}; +use primitives::{Address, AddressAndId, Bytes}; /// Represents the outcome of a create operation in an interpreter. /// @@ -12,7 +12,7 @@ pub struct CreateOutcome { /// The result of the interpreter operation pub result: InterpreterResult, /// An optional address associated with the create operation - pub address: Option
, + pub address: Option, } impl CreateOutcome { @@ -26,7 +26,7 @@ impl CreateOutcome { /// # Returns /// /// A new [`CreateOutcome`] instance. - pub fn new(result: InterpreterResult, address: Option
) -> Self { + pub fn new(result: InterpreterResult, address: Option) -> Self { Self { result, address } } From d70afcd9e713e95e5b9403d7135860c58c4767a0 Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 9 Aug 2025 17:06:51 +0200 Subject: [PATCH 04/37] more transitions to account_id --- Cargo.lock | 493 ------------------ Cargo.toml | 20 +- bins/revme/src/cmd/bench/transfer.rs | 3 +- .../context/interface/src/journaled_state.rs | 18 +- crates/context/src/journal.rs | 21 + crates/context/src/journal/entry.rs | 9 +- crates/context/src/journal/inner.rs | 56 +- crates/context/src/journal/warm_addresses.rs | 40 +- crates/ee-tests/src/revm_tests.rs | 37 +- crates/handler/src/execution.rs | 37 +- crates/handler/src/handler.rs | 14 +- crates/handler/src/pre_execution.rs | 9 +- crates/inspector/src/gas.rs | 4 +- crates/inspector/src/inspector.rs | 14 +- crates/inspector/src/inspector_tests.rs | 2 +- crates/op-revm/src/handler.rs | 51 +- crates/primitives/src/address.rs | 9 + .../src/precompile_provider.rs | 8 +- 18 files changed, 238 insertions(+), 607 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 520e764388..f5ef40a80a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,7 +277,6 @@ dependencies = [ "alloy-signer", "alloy-sol-types", "alloy-transport", - "alloy-transport-http", "async-stream", "async-trait", "auto_impl", @@ -289,13 +288,11 @@ dependencies = [ "lru", "parking_lot", "pin-project", - "reqwest", "serde", "serde_json", "thiserror", "tokio", "tracing", - "url", "wasmtimer", ] @@ -330,11 +327,9 @@ dependencies = [ "alloy-json-rpc", "alloy-primitives", "alloy-transport", - "alloy-transport-http", "async-stream", "futures", "pin-project", - "reqwest", "serde", "serde_json", "tokio", @@ -342,7 +337,6 @@ dependencies = [ "tower", "tracing", "tracing-futures", - "url", "wasmtimer", ] @@ -512,21 +506,6 @@ dependencies = [ "wasmtimer", ] -[[package]] -name = "alloy-transport-http" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b234272ee449e32c9f1afbbe4ee08ea7c4b52f14479518f95c844ab66163c545" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "reqwest", - "serde_json", - "tower", - "tracing", - "url", -] - [[package]] name = "alloy-trie" version = "0.8.1" @@ -1436,16 +1415,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1825,101 +1794,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "example-block-traces" -version = "0.0.0" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-provider", - "anyhow", - "indicatif", - "revm", - "tokio", -] - -[[package]] -name = "example-cheatcode-inspector" -version = "0.0.0" -dependencies = [ - "anyhow", - "revm", -] - -[[package]] -name = "example-contract-deployment" -version = "0.0.0" -dependencies = [ - "anyhow", - "revm", -] - -[[package]] -name = "example-custom-opcodes" -version = "0.0.0" -dependencies = [ - "revm", -] - -[[package]] -name = "example-custom-precompile-journal" -version = "0.1.0" -dependencies = [ - "anyhow", - "revm", -] - -[[package]] -name = "example-database-components" -version = "0.0.0" -dependencies = [ - "auto_impl", - "revm", - "thiserror", -] - -[[package]] -name = "example-erc20-gas" -version = "0.0.0" -dependencies = [ - "alloy-provider", - "alloy-sol-types", - "anyhow", - "revm", - "tokio", -] - -[[package]] -name = "example-my-evm" -version = "0.0.0" -dependencies = [ - "revm", -] - -[[package]] -name = "example-uniswap-get-reserves" -version = "0.0.0" -dependencies = [ - "alloy-eips", - "alloy-provider", - "alloy-sol-types", - "anyhow", - "revm", - "tokio", -] - -[[package]] -name = "example-uniswap-v2-usdc-swap" -version = "0.0.0" -dependencies = [ - "alloy-eips", - "alloy-provider", - "alloy-sol-types", - "anyhow", - "revm", - "tokio", -] - [[package]] name = "fastrand" version = "2.3.0" @@ -1999,21 +1873,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2293,94 +2152,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "hyper" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - [[package]] name = "iana-time-zone" version = "0.1.63" @@ -2574,22 +2345,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is-terminal" version = "0.4.16" @@ -2836,34 +2591,6 @@ dependencies = [ "adler2", ] -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", -] - -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "num" version = "0.4.3" @@ -3053,50 +2780,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.103", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "p256" version = "0.13.2" @@ -3389,12 +3072,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - [[package]] name = "plain_hasher" version = "0.2.3" @@ -3735,42 +3412,6 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" -[[package]] -name = "reqwest" -version = "0.12.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" -dependencies = [ - "base64", - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "native-tls", - "percent-encoding", - "pin-project-lite", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "revm" version = "27.1.0" @@ -4176,15 +3817,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "zeroize", -] - [[package]] name = "rustversion" version = "1.0.21" @@ -4218,15 +3850,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "schemars" version = "0.9.0" @@ -4301,29 +3924,6 @@ dependencies = [ "cc", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4390,18 +3990,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.13.0" @@ -4534,16 +4122,6 @@ dependencies = [ "serde", ] -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "sp1-lib" version = "5.0.5" @@ -4704,9 +4282,6 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] [[package]] name = "synstructure" @@ -4834,13 +4409,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", - "bytes", - "libc", - "mio", "pin-project-lite", - "socket2", "tokio-macros", - "windows-sys 0.52.0", ] [[package]] @@ -4854,16 +4424,6 @@ dependencies = [ "syn 2.0.103", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.17" @@ -4916,25 +4476,6 @@ dependencies = [ "futures-util", "pin-project-lite", "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", "tower-layer", "tower-service", ] @@ -5014,12 +4555,6 @@ dependencies = [ "rlp", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "typenum" version = "1.18.0" @@ -5114,12 +4649,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -5151,15 +4680,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -5201,19 +4721,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.100" diff --git a/Cargo.toml b/Cargo.toml index 91b5e3b83e..c8d6409e0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,16 +25,16 @@ members = [ "crates/ee-tests", # examples - "examples/block_traces", - "examples/cheatcode_inspector", - "examples/contract_deployment", - "examples/database_components", - "examples/uniswap_get_reserves", - "examples/uniswap_v2_usdc_swap", - "examples/erc20_gas", - "examples/my_evm", - "examples/custom_opcodes", - "examples/custom_precompile_journal", + # "examples/block_traces", + # "examples/cheatcode_inspector", + # "examples/contract_deployment", + # "examples/database_components", + # "examples/uniswap_get_reserves", + # "examples/uniswap_v2_usdc_swap", + # "examples/erc20_gas", + # "examples/my_evm", + # "examples/custom_opcodes", + # "examples/custom_precompile_journal", ] resolver = "2" default-members = ["crates/revm"] diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index ac196dfe97..cccbe33f88 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -39,9 +39,10 @@ pub fn run(criterion: &mut Criterion) { let balance = evm .journal_mut() - .load_account(BENCH_TARGET) + .load_account(BENCH_TARGET.into()) .unwrap() .data + .0 .info .balance; diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index a4e93556b7..f1c5c19d37 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -67,9 +67,6 @@ pub trait JournalTr { storage_keys: impl IntoIterator, ) -> Result::Error>; - /// Warms the coinbase account. - fn warm_coinbase_account(&mut self, address: Address); - /// Warms the precompiles. Precompile account will not be fetched from database /// /// Warming of precompiles assumes that account are frequently accessed and it will @@ -123,6 +120,21 @@ pub trait JournalTr { address_or_id: AddressOrId, ) -> Result, ::Error>; + /// Sets the caller id. + fn set_caller_address_id(&mut self, id: AddressAndId); + + /// Returns the caller address and id. + fn caller_address_id(&self) -> Option; + + /// Sets the tx target address and id. + fn set_tx_target_address_id(&mut self, id: AddressAndId); + + /// Returns the tx target address and id. + fn tx_target_address_id(&self) -> Option; + + /// Warms the coinbase account. + fn warm_coinbase_account(&mut self, address: Address); + /// Loads the account delegated. fn load_account_delegated( &mut self, diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index a1682e322b..0a342212a7 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -146,10 +146,31 @@ impl JournalTr for Journal { .selfdestruct(&mut self.database, address_or_id, target) } + #[inline] fn warm_coinbase_account(&mut self, address: Address) { self.inner.warm_addresses.set_coinbase(address); } + #[inline] + fn set_caller_address_id(&mut self, id: AddressAndId) { + self.inner.warm_addresses.set_caller(id); + } + + #[inline] + fn set_tx_target_address_id(&mut self, id: AddressAndId) { + self.inner.warm_addresses.set_tx_target(id); + } + + #[inline] + fn caller_address_id(&self) -> Option { + self.inner.warm_addresses.caller() + } + + #[inline] + fn tx_target_address_id(&self) -> Option { + self.inner.warm_addresses.tx_target() + } + fn warm_precompiles(&mut self, precompiles: HashSet
) { self.inner .warm_addresses diff --git a/crates/context/src/journal/entry.rs b/crates/context/src/journal/entry.rs index e37c5e9b7c..1f827081e2 100644 --- a/crates/context/src/journal/entry.rs +++ b/crates/context/src/journal/entry.rs @@ -6,7 +6,7 @@ //! or removal of the storage slot. Check [`JournalEntryTr`] for more details. use primitives::{AccountId, Address, StorageKey, StorageValue, KECCAK_EMPTY, PRECOMPILE3, U256}; -use state::{EvmState, TransientStorage}; +use state::{EvmState, EvmStateNew, TransientStorage}; /// Trait for tracking and reverting state changes in the EVM. /// Journal entry contains information about state changes that can be reverted. @@ -81,7 +81,7 @@ pub trait JournalEntryTr { /// ``` fn revert( self, - state: &mut EvmState, + state: &mut EvmStateNew, transient_storage: Option<&mut TransientStorage>, is_spurious_dragon_enabled: bool, ); @@ -300,10 +300,12 @@ impl JournalEntryTr for JournalEntry { fn revert( self, - state: &mut EvmState, + state: &mut EvmStateNew, transient_storage: Option<&mut TransientStorage>, is_spurious_dragon_enabled: bool, ) { + todo!(); + /* match self { JournalEntry::AccountWarmed { address } => { state.get_mut(&address).unwrap().mark_cold(); @@ -418,5 +420,6 @@ impl JournalEntryTr for JournalEntry { acc.info.code = None; } } + */ } } diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 5e71412469..983f2de98e 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -23,8 +23,6 @@ use std::vec::Vec; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct JournalInner { - /// The current state - pub state: EvmState, /// The current state new pub state_new: EvmStateNew, /// Transient storage that is discarded after every transaction. @@ -56,7 +54,7 @@ pub struct JournalInner { /// [EIP-161]: https://eips.ethereum.org/EIPS/eip-161 /// [EIP-6780]: https://eips.ethereum.org/EIPS/eip-6780 pub spec: SpecId, - /// Warm addresses containing both coinbase and current precompiles. + /// Warm addresses containing current precompiles and coinbase, caller and tx target addresses. pub warm_addresses: WarmAddresses, } @@ -73,7 +71,6 @@ impl JournalInner { /// In ordinary case this is precompile or beneficiary. pub fn new() -> JournalInner { Self { - state: HashMap::default(), state_new: EvmStateNew::new(), transient_storage: TransientStorage::default(), logs: Vec::new(), @@ -102,7 +99,6 @@ impl JournalInner { // Clears all field from JournalInner. Doing it this way to avoid // missing any field. let Self { - state, state_new, transient_storage, logs, @@ -114,7 +110,6 @@ impl JournalInner { } = self; // Spec precompiles and state are not changed. It is always set again execution. let _ = spec; - let _ = state; transient_storage.clear(); *depth = 0; @@ -122,7 +117,8 @@ impl JournalInner { journal.clear(); // Clear coinbase address warming for next tx - warm_addresses.clear_coinbase(); + warm_addresses.clear_addresses(); + // increment transaction id. *transaction_id += 1; logs.clear(); @@ -132,7 +128,6 @@ impl JournalInner { pub fn discard_tx(&mut self) { // if there is no journal entries, there has not been any changes. let Self { - state, state_new, transient_storage, logs, @@ -145,7 +140,7 @@ impl JournalInner { let is_spurious_dragon_enabled = spec.is_enabled_in(SPURIOUS_DRAGON); // iterate over all journals entries and revert our global state journal.drain(..).rev().for_each(|entry| { - entry.revert(state, None, is_spurious_dragon_enabled); + entry.revert(state_new, None, is_spurious_dragon_enabled); }); transient_storage.clear(); *depth = 0; @@ -153,7 +148,7 @@ impl JournalInner { *transaction_id += 1; // Clear coinbase address warming for next tx - warm_addresses.clear_coinbase(); + warm_addresses.clear_addresses(); } /// Take the [`EvmState`] and clears the journal by resetting it to initial state. @@ -165,7 +160,6 @@ impl JournalInner { // Clears all field from JournalInner. Doing it this way to avoid // missing any field. let Self { - state, state_new, transient_storage, logs, @@ -178,9 +172,12 @@ impl JournalInner { // Spec is not changed. And it is always set again in execution. let _ = spec; // Clear coinbase address warming for next tx - warm_addresses.clear_coinbase(); + warm_addresses.clear_addresses(); + + // TODO output gets changes, it is now index map + let state = mem::take(state_new); + let state = HashMap::default(); - let state = mem::take(state); logs.clear(); transient_storage.clear(); @@ -195,8 +192,8 @@ impl JournalInner { /// Return reference to state. #[inline] - pub fn state(&mut self) -> &mut EvmState { - &mut self.state + pub fn state(&mut self) -> &mut EvmStateNew { + &mut self.state_new } /// Sets SpecId. @@ -475,7 +472,7 @@ impl JournalInner { #[inline] pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) { let is_spurious_dragon_enabled = self.spec.is_enabled_in(SPURIOUS_DRAGON); - let state = &mut self.state; + let state = &mut self.state_new; let transient_storage = &mut self.transient_storage; self.depth -= 1; self.logs.truncate(checkpoint.log_i); @@ -507,25 +504,26 @@ impl JournalInner { address_or_id: AddressOrId, target: Address, ) -> Result, DB::Error> { - // TODO re check this logic + let (acc, address) = self.state_new.get_mut(&address_or_id).unwrap(); + let balance = acc.info.balance; + let spec = self.spec; - let account_load = self.load_account(db, AddressOrId::Address(target))?; - let is_cold = account_load.is_cold; - let is_empty = account_load.0.state_clear_aware_is_empty(spec); - let target = account_load.1; + let target_account_load = self.load_account(db, AddressOrId::Address(target))?; + let is_cold = target_account_load.is_cold; + let is_empty = target_account_load.0.state_clear_aware_is_empty(spec); + let (target_acc, target) = target_account_load.data; - let (acc, address) = self.state_new.get_mut(&address_or_id).unwrap(); - if address.address() != target.address() { + if target != address_or_id { // Both accounts are loaded before this point, `address` as we execute its contract. // and `target` at the beginning of the function. - let acc_balance = acc.info.balance; - - let target_account = self.state.get_mut(target.address()).unwrap(); - Self::touch_account(&mut self.journal, address.id(), target_account); - target_account.info.balance += acc_balance; + target_acc.info.balance += balance; + if !target_acc.is_touched() { + target_acc.mark_touch(); + self.journal.push(ENTRY::account_touched(target.id())); + } } - let balance = acc.info.balance; + let (acc, _) = self.state_new.get_mut(&address_or_id).unwrap(); let destroyed_status = if !acc.is_selfdestructed() { SelfdestructionRevertStatus::GloballySelfdestroyed diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs index 6e72b725f7..e84c6416bc 100644 --- a/crates/context/src/journal/warm_addresses.rs +++ b/crates/context/src/journal/warm_addresses.rs @@ -3,7 +3,7 @@ //! It is used to optimize access to precompile addresses. use bitvec::{bitvec, order::Lsb0, vec::BitVec}; -use primitives::{short_address, Address, HashSet, SHORT_ADDRESS_CAP}; +use primitives::{short_address, Address, AddressAndId, HashSet, SHORT_ADDRESS_CAP}; /// Stores addresses that are warm loaded. Contains precompiles and coinbase address. #[derive(Debug, Clone, PartialEq, Eq)] @@ -18,6 +18,10 @@ pub struct WarmAddresses { all_short_addresses: bool, /// Coinbase address. coinbase: Option
, + /// Caller address and id. + caller: Option, + /// Tx target address and id. + tx_target: Option, } impl Default for WarmAddresses { @@ -35,6 +39,8 @@ impl WarmAddresses { precompile_short_addresses: BitVec::new(), all_short_addresses: true, coinbase: None, + caller: None, + tx_target: None, } } @@ -50,6 +56,18 @@ impl WarmAddresses { self.coinbase } + /// Returns the caller address and id. + #[inline] + pub fn caller(&self) -> Option { + self.caller + } + + /// Returns the tx target address and id. + #[inline] + pub fn tx_target(&self) -> Option { + self.tx_target + } + /// Set the precompile addresses and short addresses. #[inline] pub fn set_precompile_addresses(&mut self, addresses: HashSet
) { @@ -75,10 +93,24 @@ impl WarmAddresses { self.coinbase = Some(address); } - /// Clear the coinbase address. + /// Set the coinbase address. + #[inline] + pub fn set_caller(&mut self, address: AddressAndId) { + self.caller = Some(address); + } + + /// Set the tx target address and id. + #[inline] + pub fn set_tx_target(&mut self, address: AddressAndId) { + self.tx_target = Some(address); + } + + /// Clear the coinbase/caller/tx target addresses. #[inline] - pub fn clear_coinbase(&mut self) { + pub fn clear_addresses(&mut self) { self.coinbase = None; + self.caller = None; + self.tx_target = None; } /// Returns true if the address is warm loaded. @@ -143,7 +175,7 @@ mod tests { assert!(warm_addresses.is_warm(&coinbase_addr)); // Test clearing coinbase - warm_addresses.clear_coinbase(); + warm_addresses.clear_addresses(); assert!(warm_addresses.coinbase.is_none()); assert!(!warm_addresses.is_warm(&coinbase_addr)); } diff --git a/crates/ee-tests/src/revm_tests.rs b/crates/ee-tests/src/revm_tests.rs index 8758052a36..4bf9ec7ffb 100644 --- a/crates/ee-tests/src/revm_tests.rs +++ b/crates/ee-tests/src/revm_tests.rs @@ -49,7 +49,12 @@ fn test_selfdestruct_multi_tx() { .transact_one(TxEnv::builder_for_bench().build_fill()) .unwrap(); - let destroyed_acc = evm.ctx.journal_mut().state.get_mut(&BENCH_TARGET).unwrap(); + let (destroyed_acc, _) = evm + .ctx + .journal_mut() + .state_new + .get_mut(&BENCH_TARGET.into()) + .unwrap(); // balance got transferred to 0x0000..00FFFF assert_eq!(destroyed_acc.info.balance, U256::ZERO); @@ -64,7 +69,12 @@ fn test_selfdestruct_multi_tx() { .transact_one(TxEnv::builder_for_bench().nonce(1).build_fill()) .unwrap(); - let destroyed_acc = evm.ctx.journal_mut().state.get_mut(&BENCH_TARGET).unwrap(); + let (destroyed_acc, _) = evm + .ctx + .journal_mut() + .state_new + .get_mut(&BENCH_TARGET.into()) + .unwrap(); assert_eq!(destroyed_acc.info.code_hash, KECCAK_EMPTY); assert_eq!(destroyed_acc.info.nonce, 0); @@ -102,11 +112,11 @@ pub fn test_multi_tx_create() { let created_address = result1.created_address().unwrap(); - let created_acc = evm + let (created_acc, _) = evm .ctx .journal_mut() - .state - .get_mut(&created_address) + .state_new + .get_mut(&created_address.into()) .unwrap(); assert_eq!( @@ -126,11 +136,11 @@ pub fn test_multi_tx_create() { ) .unwrap(); - let created_acc = evm + let (created_acc, _) = evm .ctx .journal_mut() - .state - .get_mut(&created_address) + .state_new + .get_mut(&created_address.into()) .unwrap(); // reset nonce to trigger create on same address. @@ -146,9 +156,10 @@ pub fn test_multi_tx_create() { // reset caller nonce evm.ctx .journal_mut() - .state - .get_mut(&BENCH_CALLER) + .state_new + .get_mut(&BENCH_CALLER.into()) .unwrap() + .0 .info .nonce = 0; @@ -166,11 +177,11 @@ pub fn test_multi_tx_create() { let created_address_new = result3.created_address().unwrap(); assert_eq!(created_address, created_address_new); - let created_acc = evm + let (created_acc, _) = evm .ctx .journal_mut() - .state - .get_mut(&created_address) + .state_new + .get_mut(&created_address.into()) .unwrap(); assert_eq!( diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index 14cc194a2f..34602b4732 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -1,32 +1,37 @@ -use context_interface::Transaction; use interpreter::{ CallInput, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, FrameInput, }; -use primitives::TxKind; +use primitives::{AddressAndId, Bytes, U256}; use std::boxed::Box; /// Creates the first [`FrameInput`] from the transaction, spec and gas limit. -pub fn create_init_frame(tx: &impl Transaction, gas_limit: u64) -> FrameInput { - let input = tx.input().clone(); - - match tx.kind() { - TxKind::Call(target_address) => FrameInput::Call(Box::new(CallInputs { +pub fn create_init_frame( + is_call: bool, + caller: AddressAndId, + target: AddressAndId, + input: Bytes, + value: U256, + gas_limit: u64, +) -> FrameInput { + if is_call { + FrameInput::Call(Box::new(CallInputs { input: CallInput::Bytes(input), gas_limit, - target_address, - bytecode_address: target_address, - caller: tx.caller(), - value: CallValue::Transfer(tx.value()), + target_address: target, + bytecode_address: target, + caller: caller, + value: CallValue::Transfer(value), scheme: CallScheme::Call, is_static: false, return_memory_offset: 0..0, - })), - TxKind::Create => FrameInput::Create(Box::new(CreateInputs { - caller: tx.caller(), + })) + } else { + FrameInput::Create(Box::new(CreateInputs { + caller, scheme: CreateScheme::Create, - value: tx.value(), + value, init_code: input, gas_limit, - })), + })) } } diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index ad0c73ba96..345af9a958 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -293,10 +293,22 @@ pub trait Handler { let memory = SharedMemory::new_with_buffer(evm.ctx().local().shared_memory_buffer().clone()); let ctx = evm.ctx_ref(); + + let caller = ctx.journal().caller_address_id().expect("caller id is set"); + let target = ctx + .journal() + .tx_target_address_id() + .expect("tx target id is set"); + let tx = ctx.tx(); + let input = tx.input().clone(); + let value = tx.value(); + let is_call = tx.kind().is_call(); Ok(FrameInit { depth: 0, memory, - frame_input: execution::create_init_frame(ctx.tx(), gas_limit), + frame_input: execution::create_init_frame( + is_call, caller, target, input, value, gas_limit, + ), }) } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 8a5b9715a5..c9085dcbf0 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -13,8 +13,8 @@ use context_interface::{ Block, Cfg, Database, }; use core::cmp::Ordering; -use primitives::StorageKey; use primitives::{eip7702, hardfork::SpecId, KECCAK_EMPTY, U256}; +use primitives::{StorageKey, TxKind}; use state::AccountInfo; use std::boxed::Box; @@ -63,6 +63,12 @@ pub fn load_accounts< } } + // load tx target and set its id in journal. + if let TxKind::Call(target) = tx.kind() { + let (_, id) = journal.load_account_code(target.into())?.data; + journal.set_tx_target_address_id(id); + } + Ok(()) } @@ -173,6 +179,7 @@ pub fn validate_against_state_and_deduct_caller< caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } + journal.set_caller_address_id(caller); journal.caller_accounting_journal_entry(caller.to_id(), old_balance, tx.kind().is_call()); Ok(()) } diff --git a/crates/inspector/src/gas.rs b/crates/inspector/src/gas.rs index db286d4ca1..94ac777ca5 100644 --- a/crates/inspector/src/gas.rs +++ b/crates/inspector/src/gas.rs @@ -86,7 +86,7 @@ mod tests { interpreter_types::{Jumps, ReturnData}, CallInputs, CreateInputs, Interpreter, InterpreterResult, InterpreterTypes, }; - use primitives::{Address, Bytes, TxKind}; + use primitives::{Address, AddressAndId, Bytes, TxKind}; use state::bytecode::{opcode, Bytecode}; #[derive(Default, Debug)] @@ -222,7 +222,7 @@ mod tests { inspector.call_override.push(None); inspector.create_override.push(Some(CreateOutcome::new( InterpreterResult::new(InstructionResult::Revert, [0x02].into(), Gas::new(100_000)), - Some(Address::ZERO), + Some(AddressAndId::new(Address::ZERO, 0)), ))); let contract_data: Bytes = Bytes::from(vec![ diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 7a2101c377..732f7f70a9 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -5,7 +5,7 @@ use interpreter::{ InterpreterTypes, }; use primitives::{Address, Log, U256}; -use state::EvmState; +use state::EvmStateNew; /// EVM hooks into execution. /// @@ -124,10 +124,10 @@ pub trait JournalExt { fn journal(&self) -> &[JournalEntry]; /// Return the current Journaled state. - fn evm_state(&self) -> &EvmState; + fn evm_state(&self) -> &EvmStateNew; /// Return the mutable current Journaled state. - fn evm_state_mut(&mut self) -> &mut EvmState; + fn evm_state_mut(&mut self) -> &mut EvmStateNew; } impl JournalExt for Journal { @@ -142,12 +142,12 @@ impl JournalExt for Journal { } #[inline] - fn evm_state(&self) -> &EvmState { - &self.state + fn evm_state(&self) -> &EvmStateNew { + &self.state_new } #[inline] - fn evm_state_mut(&mut self) -> &mut EvmState { - &mut self.state + fn evm_state_mut(&mut self) -> &mut EvmStateNew { + &mut self.state_new } } diff --git a/crates/inspector/src/inspector_tests.rs b/crates/inspector/src/inspector_tests.rs index 5916a75c86..b1b0e19551 100644 --- a/crates/inspector/src/inspector_tests.rs +++ b/crates/inspector/src/inspector_tests.rs @@ -434,7 +434,7 @@ mod tests { let (call_inputs, call_outcome) = &call_events[0]; // The test setup might be using BENCH_CALLER as the default target // Just verify that a call was made and completed successfully - assert_eq!(call_inputs.target_address, BENCH_TARGET); + assert_eq!(*call_inputs.target_address.address(), BENCH_TARGET); assert!(call_outcome.is_some(), "Call should have completed"); } diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index f00414ec50..05332b2644 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -145,7 +145,7 @@ where let (tx, journal) = ctx.tx_journal_mut(); - let caller_account = journal.load_account_code(tx.caller())?.data; + let (caller_account, caller_id) = journal.load_account_code(tx.caller().into())?.data; if !is_deposit { // validates account nonce and code @@ -212,7 +212,11 @@ where // NOTE: all changes to the caller account should journaled so in case of error // we can revert the changes. - journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); + journal.caller_accounting_journal_entry( + caller_id.to_id(), + old_balance, + tx.kind().is_call(), + ); Ok(()) } @@ -367,7 +371,7 @@ where (BASE_FEE_RECIPIENT, base_fee_amount), (OPERATOR_FEE_RECIPIENT, operator_fee_cost), ] { - ctx.journal_mut().balance_incr(recipient, amount)?; + ctx.journal_mut().balance_incr(recipient.into(), amount)?; } Ok(()) @@ -414,11 +418,17 @@ where let ctx = evm.ctx(); let spec = ctx.cfg().spec(); let tx = ctx.tx(); - let caller = tx.caller(); let mint = tx.mint(); let is_system_tx = tx.is_system_transaction(); let gas_limit = tx.gas_limit(); + let caller_id = evm + .ctx() + .journal() + .caller_address_id() + .map(|i| i.to_id()) + .unwrap_or_else(|| evm.ctx().tx().caller().into()); + // discard all changes of this transaction evm.ctx().journal_mut().discard_tx(); @@ -431,7 +441,7 @@ where // Increment sender nonce and account balance for the mint amount. Deposits // always persist the mint amount, even if the transaction fails. - let acc: &mut revm::state::Account = evm.ctx().journal_mut().load_account(caller)?.data; + let (acc, _) = evm.ctx().journal_mut().load_account(caller_id)?.data; let old_balance = acc.info.balance; @@ -447,7 +457,7 @@ where // add journal entry for accounts evm.ctx() .journal_mut() - .caller_accounting_journal_entry(caller, old_balance, true); + .caller_accounting_journal_entry(caller_id, old_balance, true); // The gas used of a failed deposit post-regolith is the gas // limit of the transaction. pre-regolith, it is the gas limit @@ -664,8 +674,8 @@ mod tests { .unwrap(); // Check the account balance is updated. - let account = evm.ctx().journal_mut().load_account(caller).unwrap(); - assert_eq!(account.info.balance, U256::from(1010)); + let account = evm.ctx().journal_mut().load_account(caller.into()).unwrap(); + assert_eq!(account.0.info.balance, U256::from(1010)); } #[test] @@ -706,8 +716,8 @@ mod tests { .unwrap(); // Check the account balance is updated. - let account = evm.ctx().journal_mut().load_account(caller).unwrap(); - assert_eq!(account.info.balance, U256::from(10)); // 1058 - 1048 = 10 + let account = evm.ctx().journal_mut().load_account(caller.into()).unwrap(); + assert_eq!(account.0.info.balance, U256::from(10)); // 1058 - 1048 = 10 } #[test] @@ -828,8 +838,8 @@ mod tests { .unwrap(); // Check the account balance is updated. - let account = evm.ctx().journal_mut().load_account(caller).unwrap(); - assert_eq!(account.info.balance, U256::from(1)); + let account = evm.ctx().journal_mut().load_account(caller.into()).unwrap(); + assert_eq!(account.0.info.balance, U256::from(1)); } #[test] @@ -869,8 +879,8 @@ mod tests { .unwrap(); // Check the account balance is updated. - let account = evm.ctx().journal_mut().load_account(caller).unwrap(); - assert_eq!(account.info.balance, U256::from(1)); + let account = evm.ctx().journal_mut().load_account(caller.into()).unwrap(); + assert_eq!(account.0.info.balance, U256::from(1)); } #[test] @@ -1016,8 +1026,9 @@ mod tests { .0 .ctx .journal_mut() - .load_account(Address::ZERO) + .load_account(Address::ZERO.into()) .unwrap() + .0 .is_touched()); let handler = @@ -1031,8 +1042,9 @@ mod tests { .0 .ctx .journal_mut() - .load_account(Address::ZERO) + .load_account(Address::ZERO.into()) .unwrap() + .0 .is_touched()); } @@ -1106,8 +1118,8 @@ mod tests { } // Check that the caller was reimbursed the correct amount of ETH. - let account = evm.ctx().journal_mut().load_account(SENDER).unwrap(); - assert_eq!(account.info.balance, expected_refund); + let account = evm.ctx().journal_mut().load_account(SENDER.into()).unwrap(); + assert_eq!(account.0.info.balance, expected_refund); } #[test] @@ -1135,8 +1147,9 @@ mod tests { evm.0 .ctx .journal_mut() - .load_account(Address::ZERO) + .load_account(Address::ZERO.into()) .unwrap() + .0 .info .nonce, 0 diff --git a/crates/primitives/src/address.rs b/crates/primitives/src/address.rs index d6145a4c2a..c421a50172 100644 --- a/crates/primitives/src/address.rs +++ b/crates/primitives/src/address.rs @@ -76,6 +76,15 @@ pub struct AddressAndId { id: AccountId, } +impl PartialEq for AddressAndId { + fn eq(&self, other: &AddressOrId) -> bool { + match other { + AddressOrId::Address(address) => self.address == *address, + AddressOrId::Id(id) => self.id == *id, + } + } +} + impl AddressAndId { /// Creates a new address and id. #[inline] diff --git a/examples/custom_precompile_journal/src/precompile_provider.rs b/examples/custom_precompile_journal/src/precompile_provider.rs index caab5682fd..83ed4ba88f 100644 --- a/examples/custom_precompile_journal/src/precompile_provider.rs +++ b/examples/custom_precompile_journal/src/precompile_provider.rs @@ -157,7 +157,7 @@ fn handle_read_storage(context: &mut CTX, gas_limit: u64) -> Pre // Read from storage using the journal let value = context .journal_mut() - .sload(CUSTOM_PRECOMPILE_ADDRESS, STORAGE_KEY) + .sload(CUSTOM_PRECOMPILE_ADDRESS.into(), STORAGE_KEY) .map_err(|e| PrecompileError::Other(format!("Storage read failed: {e:?}")))? .data; @@ -188,7 +188,7 @@ fn handle_write_storage( // Store the value in the precompile's storage context .journal_mut() - .sstore(CUSTOM_PRECOMPILE_ADDRESS, STORAGE_KEY, value) + .sstore(CUSTOM_PRECOMPILE_ADDRESS.into(), STORAGE_KEY, value) .map_err(|e| PrecompileError::Other(format!("Storage write failed: {e:?}")))?; // Get the caller address @@ -198,13 +198,13 @@ fn handle_write_storage( // First, ensure the precompile has balance context .journal_mut() - .balance_incr(CUSTOM_PRECOMPILE_ADDRESS, U256::from(1)) + .balance_incr(CUSTOM_PRECOMPILE_ADDRESS.into(), U256::from(1)) .map_err(|e| PrecompileError::Other(format!("Balance increment failed: {e:?}")))?; // Then transfer to caller let transfer_result = context .journal_mut() - .transfer(CUSTOM_PRECOMPILE_ADDRESS, caller, U256::from(1)) + .transfer(CUSTOM_PRECOMPILE_ADDRESS.into(), caller.into(), U256::from(1)) .map_err(|e| PrecompileError::Other(format!("Transfer failed: {e:?}")))?; if let Some(error) = transfer_result { From 4f081804209ac2a93751e4fab98c8e6e2f6a1fa2 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Aug 2025 16:09:08 +0200 Subject: [PATCH 05/37] journal entry, and integration --- crates/context/src/context.rs | 3 +- crates/context/src/journal.rs | 2 +- crates/context/src/journal/entry.rs | 178 +++++++++++++--------------- crates/context/src/journal/inner.rs | 151 ++++++++++++----------- crates/ee-tests/src/revm_tests.rs | 12 +- crates/inspector/src/handler.rs | 56 ++++----- crates/state/src/account.rs | 2 +- crates/state/src/types.rs | 153 ++++++++++-------------- 8 files changed, 260 insertions(+), 297 deletions(-) diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index fb533b3a13..e645ef11e5 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -8,8 +8,7 @@ use context_interface::{ use database_interface::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}; use derive_where::derive_where; use primitives::{ - hardfork::SpecId, Address, AddressAndId, AddressOrId, Bytes, Log, StorageKey, StorageValue, - B256, U256, + hardfork::SpecId, Address, AddressOrId, Bytes, Log, StorageKey, StorageValue, B256, U256, }; /// EVM context contains data that EVM needs for execution. diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 0a342212a7..1e33feea31 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -221,7 +221,7 @@ impl JournalTr for Journal { #[inline] fn touch_account(&mut self, address_or_id: AddressOrId) { - self.inner.touch(&address_or_id); + self.inner.touch(address_or_id); } #[inline] diff --git a/crates/context/src/journal/entry.rs b/crates/context/src/journal/entry.rs index 1f827081e2..1fc7148b2b 100644 --- a/crates/context/src/journal/entry.rs +++ b/crates/context/src/journal/entry.rs @@ -5,8 +5,8 @@ //! They are created when there is change to the state from loading (making it warm), changes to the balance, //! or removal of the storage slot. Check [`JournalEntryTr`] for more details. -use primitives::{AccountId, Address, StorageKey, StorageValue, KECCAK_EMPTY, PRECOMPILE3, U256}; -use state::{EvmState, EvmStateNew, TransientStorage}; +use primitives::{AccountId, StorageKey, StorageValue, KECCAK_EMPTY, PRECOMPILE3, U256}; +use state::{EvmStateNew, TransientStorage}; /// Trait for tracking and reverting state changes in the EVM. /// Journal entry contains information about state changes that can be reverted. @@ -114,7 +114,7 @@ pub enum JournalEntry { /// Revert: we will remove account from state. AccountWarmed { /// Address of warmed account. - address: Address, + account_id: AccountId, }, /// Mark account to be destroyed and journal balance to be reverted /// Action: Mark account and transfer the balance @@ -122,10 +122,10 @@ pub enum JournalEntry { AccountDestroyed { /// Balance of account got transferred to target. had_balance: U256, - /// Address of account to be destroyed. - address: Address, - /// Address of account that received the balance. - target: Address, + /// Account that is destroyed. + account_id: AccountId, + /// Account that received the balance. + target: AccountId, /// Status of selfdestruction revert. destroyed_status: SelfdestructionRevertStatus, }, @@ -135,7 +135,7 @@ pub enum JournalEntry { /// Revert: Unmark account touched AccountTouched { /// Address of account that is touched. - address: Address, + account_id: AccountId, }, /// Balance changed /// Action: Balance changed @@ -144,7 +144,7 @@ pub enum JournalEntry { /// New balance of account. old_balance: U256, /// Address of account that had its balance changed. - address: Address, + account_id: AccountId, }, /// Transfer balance between two accounts /// Action: Transfer balance @@ -153,9 +153,9 @@ pub enum JournalEntry { /// Balance that is transferred. balance: U256, /// Address of account that sent the balance. - from: Address, + from: AccountId, /// Address of account that received the balance. - to: Address, + to: AccountId, }, /// Increment nonce /// Action: Increment nonce by one @@ -163,7 +163,7 @@ pub enum JournalEntry { NonceChange { /// Address of account that had its nonce changed. /// Nonce is incremented by one. - address: Address, + account_id: AccountId, }, /// Create account: /// Actions: Mark account as created @@ -171,7 +171,7 @@ pub enum JournalEntry { AccountCreated { /// Address of account that is created. /// On revert, this account will be set to empty. - address: Address, + account_id: AccountId, /// If account is created globally for first time. is_created_globally: bool, }, @@ -184,7 +184,7 @@ pub enum JournalEntry { /// Previous value of storage slot. had_value: StorageValue, /// Address of account that had its storage changed. - address: Address, + account_id: AccountId, }, /// Entry used to track storage warming introduced by EIP-2929. /// Action: Storage warmed @@ -193,7 +193,7 @@ pub enum JournalEntry { /// Key of storage slot that is warmed. key: StorageKey, /// Address of account that had its storage warmed. By SLOAD or SSTORE opcode. - address: Address, + account_id: AccountId, }, /// It is used to track an EIP-1153 transient storage change. /// Action: Transient storage changed. @@ -204,20 +204,19 @@ pub enum JournalEntry { /// Previous value of transient storage slot. had_value: StorageValue, /// Address of account that had its transient storage changed. - address: Address, + account_id: AccountId, }, /// Code changed /// Action: Account code changed /// Revert: Revert to previous bytecode. CodeChange { /// Address of account that had its code changed. - address: Address, + account_id: AccountId, }, } impl JournalEntryTr for JournalEntry { fn account_warmed(account_id: AccountId) -> Self { - // JournalEntry::AccountWarmed { account_id } - todo!() + JournalEntry::AccountWarmed { account_id } } fn account_destroyed( @@ -226,58 +225,50 @@ impl JournalEntryTr for JournalEntry { destroyed_status: SelfdestructionRevertStatus, had_balance: StorageValue, ) -> Self { - // JournalEntry::AccountDestroyed { - // address, - // target, - // destroyed_status, - // had_balance, - // } - todo!() + JournalEntry::AccountDestroyed { + account_id, + target, + destroyed_status, + had_balance, + } } fn account_touched(account_id: AccountId) -> Self { - // JournalEntry::AccountTouched { account_id } - todo!() + JournalEntry::AccountTouched { account_id } } fn balance_changed(account_id: AccountId, old_balance: U256) -> Self { - // JournalEntry::BalanceChange { - // account_id, - // old_balance, - // } - todo!() + JournalEntry::BalanceChange { + account_id, + old_balance, + } } fn balance_transfer(from: AccountId, to: AccountId, balance: U256) -> Self { - // JournalEntry::BalanceTransfer { from, to, balance } - todo!() + JournalEntry::BalanceTransfer { from, to, balance } } fn account_created(account_id: AccountId, is_created_globally: bool) -> Self { - // JournalEntry::AccountCreated { - // account_id, - // is_created_globally, - // } - todo!() + JournalEntry::AccountCreated { + account_id, + is_created_globally, + } } fn storage_changed(account_id: AccountId, key: StorageKey, had_value: StorageValue) -> Self { - // JournalEntry::StorageChanged { - // account_id, - // key, - // had_value, - // } - todo!() + JournalEntry::StorageChanged { + account_id, + key, + had_value, + } } fn nonce_changed(account_id: AccountId) -> Self { - // JournalEntry::NonceChange { account_id } - todo!() + JournalEntry::NonceChange { account_id } } fn storage_warmed(account_id: AccountId, key: StorageKey) -> Self { - // JournalEntry::StorageWarmed { account_id, key } - todo!() + JournalEntry::StorageWarmed { account_id, key } } fn transient_storage_changed( @@ -285,17 +276,15 @@ impl JournalEntryTr for JournalEntry { key: StorageKey, had_value: StorageValue, ) -> Self { - // JournalEntry::TransientStorageChange { - // address, - // key, - // had_value, - // } - todo!() + JournalEntry::TransientStorageChange { + account_id, + key, + had_value, + } } fn code_changed(account_id: AccountId) -> Self { - // JournalEntry::CodeChange { account_id } - todo!() + JournalEntry::CodeChange { account_id } } fn revert( @@ -304,26 +293,25 @@ impl JournalEntryTr for JournalEntry { transient_storage: Option<&mut TransientStorage>, is_spurious_dragon_enabled: bool, ) { - todo!(); - /* match self { - JournalEntry::AccountWarmed { address } => { - state.get_mut(&address).unwrap().mark_cold(); + JournalEntry::AccountWarmed { account_id } => { + state.get_mut(account_id.into()).unwrap().0.mark_cold(); } - JournalEntry::AccountTouched { address } => { - if is_spurious_dragon_enabled && address == PRECOMPILE3 { + JournalEntry::AccountTouched { account_id } => { + // remove touched status + let (account, address) = state.get_mut(account_id.into()).unwrap(); + if is_spurious_dragon_enabled && *address.address() == PRECOMPILE3 { return; } - // remove touched status - state.get_mut(&address).unwrap().unmark_touch(); + account.unmark_touch(); } JournalEntry::AccountDestroyed { - address, + account_id, target, destroyed_status, had_balance, } => { - let account = state.get_mut(&address).unwrap(); + let (account, address) = state.get_mut(account_id.into()).unwrap(); // set previous state of selfdestructed flag, as there could be multiple // selfdestructs in one transaction. match destroyed_status { @@ -340,33 +328,34 @@ impl JournalEntryTr for JournalEntry { account.info.balance += had_balance; - if address != target { - let target = state.get_mut(&target).unwrap(); + // account id is same for same account. + if address.id() != target { + let target = state.get_mut(target.into()).unwrap().0; target.info.balance -= had_balance; } } JournalEntry::BalanceChange { - address, + account_id, old_balance, } => { - let account = state.get_mut(&address).unwrap(); + let (account, _) = state.get_mut(account_id.into()).unwrap(); account.info.balance = old_balance; } JournalEntry::BalanceTransfer { from, to, balance } => { // we don't need to check overflow and underflow when adding and subtracting the balance. - let from = state.get_mut(&from).unwrap(); + let (from, _) = state.get_mut(from.into()).unwrap(); from.info.balance += balance; - let to = state.get_mut(&to).unwrap(); + let (to, _) = state.get_mut(to.into()).unwrap(); to.info.balance -= balance; } - JournalEntry::NonceChange { address } => { - state.get_mut(&address).unwrap().info.nonce -= 1; + JournalEntry::NonceChange { account_id } => { + state.get_mut(account_id.into()).unwrap().0.info.nonce -= 1; } JournalEntry::AccountCreated { - address, + account_id, is_created_globally, } => { - let account = &mut state.get_mut(&address).unwrap(); + let (account, _) = state.get_mut(account_id.into()).unwrap(); account.unmark_created_locally(); if is_created_globally { account.unmark_created(); @@ -374,52 +363,53 @@ impl JournalEntryTr for JournalEntry { // only account that have nonce == 0 can be created so it is safe to set it to 0. account.info.nonce = 0; } - JournalEntry::StorageWarmed { address, key } => { + JournalEntry::StorageWarmed { account_id, key } => { state - .get_mut(&address) + .get_mut(account_id.into()) .unwrap() + .0 .storage .get_mut(&key) .unwrap() .mark_cold(); } JournalEntry::StorageChanged { - address, + account_id, key, had_value, } => { state - .get_mut(&address) + .get_mut(account_id.into()) .unwrap() + .0 .storage .get_mut(&key) .unwrap() .present_value = had_value; } JournalEntry::TransientStorageChange { - address, + account_id, key, had_value, } => { let Some(transient_storage) = transient_storage else { return; }; - let tkey = (address, key); - // if had_value.is_zero() { - // // if previous value is zero, remove it - // transient_storage.remove(&tkey); - // } else { - // // if not zero, reinsert old value to transient storage. - // transient_storage.insert(tkey, had_value); - // } + let tkey = (account_id, key); + if had_value.is_zero() { + // if previous value is zero, remove it + transient_storage.remove(&tkey); + } else { + // if not zero, reinsert old value to transient storage. + transient_storage.insert(tkey, had_value); + } todo!() } - JournalEntry::CodeChange { address } => { - let acc = state.get_mut(&address).unwrap(); + JournalEntry::CodeChange { account_id } => { + let (acc, _) = state.get_mut(account_id.into()).unwrap(); acc.info.code_hash = KECCAK_EMPTY; acc.info.code = None; } } - */ } } diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 983f2de98e..28d21cae89 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -206,7 +206,7 @@ impl JournalInner { /// This is especially important for state clear where touched empty accounts needs to /// be removed from state. #[inline] - pub fn touch(&mut self, address_or_id: &AddressOrId) { + pub fn touch(&mut self, address_or_id: AddressOrId) { if let Some((account, id)) = self.state_new.get_mut(address_or_id) { Self::touch_account(&mut self.journal, id.id(), account); } @@ -240,7 +240,7 @@ impl JournalInner { /// Note: Assume account is warm and that hash is calculated from code. #[inline] pub fn set_code_with_hash(&mut self, address_or_id: AddressOrId, code: Bytecode, hash: B256) { - let (account, address) = self.state_new.get_mut(&address_or_id).unwrap(); + let (account, address) = self.state_new.get_mut(address_or_id).unwrap(); Self::touch_account(&mut self.journal, address.id(), account); self.journal.push(ENTRY::code_changed(address.id())); @@ -332,7 +332,7 @@ impl JournalInner { ) -> Result, DB::Error> { if balance.is_zero() { self.load_account(db, to)?; - let (to_account, to) = self.state_new.get_mut(&to).unwrap(); + let (to_account, to) = self.state_new.get_mut(to).unwrap(); Self::touch_account(&mut self.journal, to.id(), to_account); return Ok(None); } @@ -341,7 +341,7 @@ impl JournalInner { let (_, from) = self.load_account(db, from)?.data; // sub balance from - let (from_account, from) = self.state_new.get_mut(&AddressOrId::Id(from.id())).unwrap(); + let (from_account, from) = self.state_new.get_mut(AddressOrId::Id(from.id())).unwrap(); Self::touch_account(&mut self.journal, from.id(), from_account); let from_balance = &mut from_account.info.balance; @@ -351,7 +351,7 @@ impl JournalInner { *from_balance = from_balance_decr; // add balance to - let (to_account, to) = self.state_new.get_mut(&AddressOrId::Id(to.id())).unwrap(); + let (to_account, to) = self.state_new.get_mut(AddressOrId::Id(to.id())).unwrap(); Self::touch_account(&mut self.journal, to.id(), to_account); let to_balance = &mut to_account.info.balance; let Some(to_balance_incr) = to_balance.checked_add(balance) else { @@ -402,7 +402,7 @@ impl JournalInner { } // Newly created account is present, as we just loaded it. - let (target_acc, target) = self.state_new.get_mut(&target_or_id).unwrap(); + let (target_acc, target) = self.state_new.get_mut(target_or_id).unwrap(); let last_journal = &mut self.journal; // New account can be created if: @@ -439,7 +439,7 @@ impl JournalInner { // safe to decrement for the caller as balance check is already done. self.state_new - .get_mut(&AddressOrId::Id(caller.id())) + .get_mut(AddressOrId::Id(caller.id())) .unwrap() .0 .info @@ -504,7 +504,7 @@ impl JournalInner { address_or_id: AddressOrId, target: Address, ) -> Result, DB::Error> { - let (acc, address) = self.state_new.get_mut(&address_or_id).unwrap(); + let (acc, address) = self.state_new.get_mut(address_or_id).unwrap(); let balance = acc.info.balance; let spec = self.spec; @@ -523,7 +523,7 @@ impl JournalInner { } } - let (acc, _) = self.state_new.get_mut(&address_or_id).unwrap(); + let (acc, _) = self.state_new.get_mut(address_or_id).unwrap(); let destroyed_status = if !acc.is_selfdestructed() { SelfdestructionRevertStatus::GloballySelfdestroyed @@ -643,73 +643,72 @@ impl JournalInner { load_code: bool, storage_keys: impl IntoIterator, ) -> Result, DB::Error> { - todo!(); - //let load = Default::default(); - //let id = AddressAndId::new(address_or_id.address().unwrap(), 0); - // let load = match self.state.entry(address) { - // Entry::Occupied(entry) => { - // let account = entry.into_mut(); - // let is_cold = account.mark_warm_with_transaction_id(self.transaction_id); - // // if it is colad loaded we need to clear local flags that can interact with selfdestruct - // if is_cold { - // // if it is cold loaded and we have selfdestructed locally it means that - // // account was selfdestructed in previous transaction and we need to clear its information and storage. - // if account.is_selfdestructed_locally() { - // account.selfdestruct(); - // account.unmark_selfdestructed_locally(); - // } - // // unmark locally created - // account.unmark_created_locally(); - // } - // StateLoad { - // data: account, - // is_cold, - // } - // } - // Entry::Vacant(vac) => { - // let account = if let Some(account) = db.basic(address)? { - // account.into() - // } else { - // Account::new_not_existing(self.transaction_id) - // }; - - // // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account - // let is_cold = self.warm_addresses.is_cold(&address); - - // StateLoad { - // data: vac.insert(account), - // is_cold, - // } - // } - // }; + let (account, address_and_id) = match address_or_id { + AddressOrId::Address(address) => self.state_new.get_mut_or_fetch( + address, + |address| -> Result { + db.basic(address).map(|account| { + if let Some(account) = account { + account.into() + } else { + Account::new_not_existing(self.transaction_id) + } + }) + }, + )?, + AddressOrId::Id(id) => self.state_new.get_by_id_mut(id).unwrap(), + }; + + let mut is_cold = account.mark_warm_with_transaction_id(self.transaction_id); + + if is_cold { + // if it is cold loaded and we have selfdestructed locally it means that + // account was selfdestructed in previous transaction and we need to clear its information and storage. + if account.is_selfdestructed_locally() { + account.selfdestruct(); + account.unmark_selfdestructed_locally(); + } + // unmark locally created + account.unmark_created_locally(); + + // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account + is_cold = self.warm_addresses.is_cold(address_and_id.address()); + } + + let mut load = StateLoad { + data: (account, address_and_id), + is_cold, + }; // journal loading of cold account. - // if load.is_cold { - // self.journal.push(ENTRY::account_warmed(id.id())); - // } - // if load_code { - // let info = &mut load.data.info; - // if info.code.is_none() { - // let code = if info.code_hash == KECCAK_EMPTY { - // Bytecode::default() - // } else { - // db.code_by_hash(info.code_hash)? - // }; - // info.code = Some(code); - // } - // } - - // for storage_key in storage_keys.into_iter() { - // sload_with_account( - // load.data, - // db, - // &mut self.journal, - // self.transaction_id, - // id, - // storage_key, - // )?; - // } - // Ok((load, id)) + if load.is_cold { + self.journal + .push(ENTRY::account_warmed(address_and_id.id())); + } + if load_code { + let info = &mut load.data.0.info; + if info.code.is_none() { + let code = if info.code_hash == KECCAK_EMPTY { + Bytecode::default() + } else { + db.code_by_hash(info.code_hash)? + }; + info.code = Some(code); + } + } + + for storage_key in storage_keys.into_iter() { + sload_with_account( + &mut load.data.0, + db, + &mut self.journal, + self.transaction_id, + address_and_id, + storage_key, + )?; + } + + Ok(load) } /// Loads storage slot. @@ -725,7 +724,7 @@ impl JournalInner { key: StorageKey, ) -> Result, DB::Error> { // assume acc is warm - let (account, id) = self.state_new.get_mut(&address_or_id).unwrap(); + let (account, id) = self.state_new.get_mut(address_or_id).unwrap(); // only if account is created in this tx we can assume that storage is empty. sload_with_account(account, db, &mut self.journal, self.transaction_id, id, key) } @@ -745,7 +744,7 @@ impl JournalInner { ) -> Result, DB::Error> { // assume that acc exists and load the slot. let present = self.sload(db, address_or_id, key)?; - let (acc, id) = self.state_new.get_mut(&address_or_id).unwrap(); + let (acc, id) = self.state_new.get_mut(address_or_id).unwrap(); // if there is no original value in dirty return present value, that is our original. let slot = acc.storage.get_mut(&key).unwrap(); diff --git a/crates/ee-tests/src/revm_tests.rs b/crates/ee-tests/src/revm_tests.rs index 4bf9ec7ffb..dcdd9b6da8 100644 --- a/crates/ee-tests/src/revm_tests.rs +++ b/crates/ee-tests/src/revm_tests.rs @@ -53,7 +53,7 @@ fn test_selfdestruct_multi_tx() { .ctx .journal_mut() .state_new - .get_mut(&BENCH_TARGET.into()) + .get_mut(BENCH_TARGET.into()) .unwrap(); // balance got transferred to 0x0000..00FFFF @@ -73,7 +73,7 @@ fn test_selfdestruct_multi_tx() { .ctx .journal_mut() .state_new - .get_mut(&BENCH_TARGET.into()) + .get_mut(BENCH_TARGET.into()) .unwrap(); assert_eq!(destroyed_acc.info.code_hash, KECCAK_EMPTY); @@ -116,7 +116,7 @@ pub fn test_multi_tx_create() { .ctx .journal_mut() .state_new - .get_mut(&created_address.into()) + .get_mut(created_address.into()) .unwrap(); assert_eq!( @@ -140,7 +140,7 @@ pub fn test_multi_tx_create() { .ctx .journal_mut() .state_new - .get_mut(&created_address.into()) + .get_mut(created_address.into()) .unwrap(); // reset nonce to trigger create on same address. @@ -157,7 +157,7 @@ pub fn test_multi_tx_create() { evm.ctx .journal_mut() .state_new - .get_mut(&BENCH_CALLER.into()) + .get_mut(BENCH_CALLER.into()) .unwrap() .0 .info @@ -181,7 +181,7 @@ pub fn test_multi_tx_create() { .ctx .journal_mut() .state_new - .get_mut(&created_address.into()) + .get_mut(created_address.into()) .unwrap(); assert_eq!( diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index aad34460cc..2af177c7bf 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -231,9 +231,9 @@ where // Handle selfdestruct. if let InterpreterAction::Return(result) = &next_action { - if result.result == InstructionResult::SelfDestruct { - inspect_selfdestruct(context, &mut inspector); - } + // if result.result == InstructionResult::SelfDestruct { + // inspect_selfdestruct(context, &mut inspector); + // } } next_action @@ -263,28 +263,28 @@ fn inspect_log( inspector.log(interpreter, context, log); } -#[inline(never)] -#[cold] -fn inspect_selfdestruct(context: &mut CTX, inspector: &mut impl Inspector) -where - CTX: ContextTr + Host, - IT: InterpreterTypes, -{ - if let Some( - JournalEntry::AccountDestroyed { - address: contract, - target: to, - had_balance: balance, - .. - } - | JournalEntry::BalanceTransfer { - from: contract, - to, - balance, - .. - }, - ) = context.journal_mut().journal().last() - { - inspector.selfdestruct(*contract, *to, *balance); - } -} +// #[inline(never)] +// #[cold] +// fn inspect_selfdestruct(context: &mut CTX, inspector: &mut impl Inspector) +// where +// CTX: ContextTr + Host, +// IT: InterpreterTypes, +// { +// if let Some( +// JournalEntry::AccountDestroyed { +// account_id: 0, +// target: to, +// had_balance: balance, +// .. +// } +// | JournalEntry::BalanceTransfer { +// from: contract, +// to, +// balance, +// .. +// }, +// ) = context.journal_mut().journal().last() +// { +// inspector.selfdestruct(*contract, *to, *balance); +// } +// } diff --git a/crates/state/src/account.rs b/crates/state/src/account.rs index a89cc293c6..fd44ba44b6 100644 --- a/crates/state/src/account.rs +++ b/crates/state/src/account.rs @@ -4,7 +4,7 @@ use crate::{AccountInfo, EvmStorage, EvmStorageSlot}; use bitflags::bitflags; use core::hash::Hash; use primitives::hardfork::SpecId; -use primitives::{Address, HashMap, StorageKey}; +use primitives::{HashMap, StorageKey}; /// Account type used inside Journal to track changed to state. #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index c3bf94dc1e..489af869ba 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -1,6 +1,6 @@ use crate::{Account, EvmStorageSlot}; use primitives::{ - AccountId, Address, AddressAndId, AddressOrId, HashMap, StorageKey, StorageValue, + map::Entry, AccountId, Address, AddressAndId, AddressOrId, HashMap, StorageKey, StorageValue, }; /// EVM State is a mapping from addresses to accounts. @@ -27,8 +27,8 @@ impl EvmStateNew { /// Create a new empty state. pub fn new() -> Self { Self { - index: HashMap::default(), - accounts: Vec::new(), + index: HashMap::with_capacity(1024), + accounts: Vec::with_capacity(1024), } } @@ -56,13 +56,14 @@ impl EvmStateNew { } /// Get a mutable reference to an account by address. - pub fn get_mut(&mut self, address_or_id: &AddressOrId) -> Option<(&mut Account, AddressAndId)> { + #[inline] + pub fn get_mut(&mut self, address_or_id: AddressOrId) -> Option<(&mut Account, AddressAndId)> { match address_or_id { AddressOrId::Id(id) => self .accounts - .get_mut(*id) - .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))), - AddressOrId::Address(address) => self.index.get(address).and_then(|id| { + .get_mut(id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, id))), + AddressOrId::Address(address) => self.index.get(&address).and_then(|id| { self.accounts .get_mut(*id) .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) @@ -70,34 +71,38 @@ impl EvmStateNew { } } - /// Insert a new account or update an existing one. - pub fn insert(&mut self, address: Address, account: Account) -> AddressAndId { - todo!() - // match self.index.get(&address) { - // Some(&id) => { - // // Update existing account - // let old_account = std::mem::replace(&mut self.accounts[id], (account, address)); - // Some(old_account) - // } - // None => { - // // Insert new account - // let id = self.accounts.len(); - // self.accounts.push((account, address)); - // self.index.insert(address, id); - // None - // } - // } + /// Get an immutable reference to an account by id. + #[inline] + pub fn get_by_id(&self, id: AccountId) -> Option<(&Account, AddressAndId)> { + self.accounts + .get(id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) + } + + /// Get a mutable reference to an account by id. + #[inline] + pub fn get_by_id_mut(&mut self, id: AccountId) -> Option<(&mut Account, AddressAndId)> { + self.accounts + .get_mut(id) + .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) } - /// Remove an account by address. - pub fn remove(&mut self, address: &Address) -> Option { - todo!() - // self.index.remove(address).and_then(|id| { - // // Note: This doesn't actually remove from the Vec to avoid invalidating indices. - // // The account at this index becomes invalid and shouldn't be accessed directly. - // // A proper implementation might mark it as deleted or use a different data structure. - // self.accounts.get(id).cloned() - // }) + /// Insert a new account or update an existing one. + #[inline] + pub fn insert(&mut self, address: Address, account: Account) -> AddressAndId { + match self.index.get(&address) { + Some(&id) => { + // Update existing account + self.accounts[id] = (account, address); + AddressAndId::new(address, id) + } + None => { + let id = self.accounts.len(); + self.index.insert(address, id); + self.accounts.push((account, address)); + AddressAndId::new(address, id) + } + } } /// Check if an account exists. @@ -125,63 +130,33 @@ impl EvmStateNew { pub fn iter(&self) -> impl Iterator + '_ { self.accounts.iter() } - /// Iterate mutably over all accounts. - /// Returns a vector of (Address, &mut Account) pairs. - /// - /// Note: This collects addresses into a Vec to avoid borrowing issues. - pub fn iter_mut(&mut self) -> Vec<(Address, &mut Account)> { - todo!() - // let mut result = Vec::new(); - // let addresses: Vec<(Address, AccountId)> = - // self.index.iter().map(|(k, &v)| (*k, v)).collect(); - - // // We need to use unsafe here to get multiple mutable references - // // This is safe because we know each AccountId maps to a unique index - // for (addr, id) in addresses { - // if let Some(account) = self.accounts.get_mut(id) { - // result.push((addr, account as *mut Account)); - // } - // } - - // // Convert raw pointers back to references - // result - // .into_iter() - // .map(|(addr, ptr)| unsafe { (addr, &mut *ptr) }) - // .collect() - } - // /// Get a mutable reference to an account, inserting a default if it doesn't exist. - // pub fn get_or_insert_default(&mut self, address: Address) -> &mut Account { - // if !self.contains_key(&address) { - // self.insert(address, Account::default()); - // } - // self.get_mut(&address).unwrap() - // } - - // /// Get a mutable reference to an account, inserting with a function if it doesn't exist. - // pub fn get_or_insert_with(&mut self, address_or_id: &AddressOrId, f: F) -> &mut Account - // where - // F: FnOnce() -> Account, - // { - // if !self.contains_key(&address) { - // self.insert(address, f()); - // } - // self.get_mut(&address).unwrap() - // } - - // /// Take ownership of the state, returning the underlying HashMap. - // pub fn take(&mut self) -> HashMap { - // let mut map = HashMap::new(); - // let index = std::mem::take(&mut self.index); - // let accounts = std::mem::take(&mut self.accounts); - - // for (address, id) in index { - // if let Some(account) = accounts.get(id) { - // map.insert(address, account.clone()); - // } - // } - // map - // } + /// Get a mutable reference to an account by address or fetch it if it doesn't exist. + #[inline] + pub fn get_mut_or_fetch( + &mut self, + address: Address, + fetch: F, + ) -> Result<(&mut Account, AddressAndId), ERROR> + where + F: FnOnce(Address) -> Result, + { + match self.index.entry(address) { + Entry::Occupied(entry) => { + let address_and_id = AddressAndId::new(address, *entry.get()); + let (account, _) = self.accounts.get_mut(*entry.get()).unwrap(); + Ok((account, address_and_id)) + } + Entry::Vacant(entry) => { + let account = fetch(address)?; + let id = self.accounts.len(); + entry.insert(id); + self.accounts.push((account, address)); + let address_and_id = AddressAndId::new(address, id); + Ok((&mut self.accounts.last_mut().unwrap().0, address_and_id)) + } + } + } } impl Default for EvmStateNew { From 569b4b7017b459a08ba794c6f19a8d36fc94d552 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Aug 2025 17:30:11 +0200 Subject: [PATCH 06/37] make load inline never --- crates/context/src/journal/inner.rs | 27 +++++++++++++-------------- crates/state/src/account.rs | 8 ++++---- crates/state/src/types.rs | 14 +------------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 28d21cae89..bae53b3912 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -635,7 +635,7 @@ impl JournalInner { } /// Loads account. If account is already loaded it will be marked as warm. - #[inline] + #[inline(never)] pub fn load_account_optional( &mut self, db: &mut DB, @@ -673,20 +673,16 @@ impl JournalInner { // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account is_cold = self.warm_addresses.is_cold(address_and_id.address()); - } - let mut load = StateLoad { - data: (account, address_and_id), - is_cold, - }; - - // journal loading of cold account. - if load.is_cold { - self.journal - .push(ENTRY::account_warmed(address_and_id.id())); + // journal loading of cold account. + if is_cold { + self.journal + .push(ENTRY::account_warmed(address_and_id.id())); + } } + if load_code { - let info = &mut load.data.0.info; + let info = &mut account.info; if info.code.is_none() { let code = if info.code_hash == KECCAK_EMPTY { Bytecode::default() @@ -699,7 +695,7 @@ impl JournalInner { for storage_key in storage_keys.into_iter() { sload_with_account( - &mut load.data.0, + account, db, &mut self.journal, self.transaction_id, @@ -708,7 +704,10 @@ impl JournalInner { )?; } - Ok(load) + Ok(StateLoad { + data: (account, address_and_id), + is_cold, + }) } /// Loads storage slot. diff --git a/crates/state/src/account.rs b/crates/state/src/account.rs index 37463c39a7..70b8683c11 100644 --- a/crates/state/src/account.rs +++ b/crates/state/src/account.rs @@ -1,7 +1,7 @@ use bitflags::bitflags; use core::hash::Hash; use primitives::hardfork::SpecId; -use primitives::{HashMap, StorageKey, StorageValue}; +use primitives::{HashMap, StorageKey}; use crate::{AccountInfo, EvmStorage, EvmStorageSlot}; @@ -326,7 +326,7 @@ impl Default for AccountStatus { mod tests { use super::*; use crate::EvmStorageSlot; - use primitives::{StorageKey, KECCAK_EMPTY, U256}; + use primitives::{StorageKey, StorageValue, KECCAK_EMPTY, U256}; #[test] fn account_is_empty_balance() { @@ -419,7 +419,7 @@ mod tests { #[test] fn test_account_with_storage() { - let mut storage = HashMap::new(); + let mut storage: HashMap = HashMap::default(); let key1 = StorageKey::from(1); let key2 = StorageKey::from(2); let slot1 = EvmStorageSlot::new(StorageValue::from(10), 0); @@ -531,7 +531,7 @@ mod tests { let slot_key = StorageKey::from(42); let slot_value = EvmStorageSlot::new(StorageValue::from(123), 0); - let mut storage = HashMap::new(); + let mut storage: HashMap = HashMap::default(); storage.insert(slot_key, slot_value.clone()); // Chain multiple builder methods together diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 489af869ba..b0791bdb4d 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -27,7 +27,7 @@ impl EvmStateNew { /// Create a new empty state. pub fn new() -> Self { Self { - index: HashMap::with_capacity(1024), + index: HashMap::default(), accounts: Vec::with_capacity(1024), } } @@ -174,15 +174,3 @@ impl From> for EvmStateNew { state } } - -// impl From for HashMap { -// fn from(state: EvmStateNew) -> Self { -// let mut map = HashMap::new(); -// for (address, id) in state.index { -// if let Some(account) = state.accounts.get(id) { -// map.insert(address, account.clone()); -// } -// } -// map -// } -// } From 8ab1352308577891d4d14a52e4e9015c8b8187b9 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Aug 2025 17:40:42 +0200 Subject: [PATCH 07/37] use new EvmState --- crates/context/src/journal/entry.rs | 6 +++--- crates/context/src/journal/inner.rs | 10 ++++------ crates/database/interface/src/either.rs | 4 ++-- crates/database/interface/src/lib.rs | 6 +++--- crates/database/interface/src/try_commit.rs | 10 +++++----- crates/database/src/in_memory_db.rs | 6 +++--- crates/database/src/states/cache.rs | 2 +- crates/database/src/states/state.rs | 4 ++-- crates/ee-tests/src/op_revm_tests.rs | 15 +++++++++------ crates/handler/src/mainnet_builder.rs | 7 ++++--- crates/handler/src/system_call.rs | 6 +++++- crates/inspector/src/inspector.rs | 10 +++++----- crates/state/src/lib.rs | 2 +- crates/state/src/types.rs | 13 +++++-------- 14 files changed, 52 insertions(+), 49 deletions(-) diff --git a/crates/context/src/journal/entry.rs b/crates/context/src/journal/entry.rs index 1fc7148b2b..0412a81644 100644 --- a/crates/context/src/journal/entry.rs +++ b/crates/context/src/journal/entry.rs @@ -6,7 +6,7 @@ //! or removal of the storage slot. Check [`JournalEntryTr`] for more details. use primitives::{AccountId, StorageKey, StorageValue, KECCAK_EMPTY, PRECOMPILE3, U256}; -use state::{EvmStateNew, TransientStorage}; +use state::{EvmState, TransientStorage}; /// Trait for tracking and reverting state changes in the EVM. /// Journal entry contains information about state changes that can be reverted. @@ -81,7 +81,7 @@ pub trait JournalEntryTr { /// ``` fn revert( self, - state: &mut EvmStateNew, + state: &mut EvmState, transient_storage: Option<&mut TransientStorage>, is_spurious_dragon_enabled: bool, ); @@ -289,7 +289,7 @@ impl JournalEntryTr for JournalEntry { fn revert( self, - state: &mut EvmStateNew, + state: &mut EvmState, transient_storage: Option<&mut TransientStorage>, is_spurious_dragon_enabled: bool, ) { diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index bae53b3912..a959d76cbe 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -15,7 +15,7 @@ use primitives::{ AccountId, Address, AddressAndId, AddressOrId, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; -use state::{Account, EvmState, EvmStateNew, EvmStorageSlot, TransientStorage}; +use state::{Account, EvmState, EvmStorageSlot, TransientStorage}; use std::vec::Vec; /// Inner journal state that contains journal and state changes. /// @@ -24,7 +24,7 @@ use std::vec::Vec; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct JournalInner { /// The current state new - pub state_new: EvmStateNew, + pub state_new: EvmState, /// Transient storage that is discarded after every transaction. /// /// See [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153). @@ -71,7 +71,7 @@ impl JournalInner { /// In ordinary case this is precompile or beneficiary. pub fn new() -> JournalInner { Self { - state_new: EvmStateNew::new(), + state_new: EvmState::new(), transient_storage: TransientStorage::default(), logs: Vec::new(), journal: Vec::default(), @@ -174,9 +174,7 @@ impl JournalInner { // Clear coinbase address warming for next tx warm_addresses.clear_addresses(); - // TODO output gets changes, it is now index map let state = mem::take(state_new); - let state = HashMap::default(); logs.clear(); transient_storage.clear(); @@ -192,7 +190,7 @@ impl JournalInner { /// Return reference to state. #[inline] - pub fn state(&mut self) -> &mut EvmStateNew { + pub fn state(&mut self) -> &mut EvmState { &mut self.state_new } diff --git a/crates/database/interface/src/either.rs b/crates/database/interface/src/either.rs index a22210cb4b..a78b730a47 100644 --- a/crates/database/interface/src/either.rs +++ b/crates/database/interface/src/either.rs @@ -3,7 +3,7 @@ use crate::{Database, DatabaseCommit, DatabaseRef}; use either::Either; use primitives::{Address, HashMap, StorageKey, StorageValue, B256}; -use state::{Account, AccountInfo, Bytecode}; +use state::{Account, AccountInfo, Bytecode, EvmState}; impl Database for Either where @@ -50,7 +50,7 @@ where L: DatabaseCommit, R: DatabaseCommit, { - fn commit(&mut self, changes: HashMap) { + fn commit(&mut self, changes: EvmState) { match self { Self::Left(db) => db.commit(changes), Self::Right(db) => db.commit(changes), diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index ab816aad16..b3ca6f92ae 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -10,7 +10,7 @@ use core::convert::Infallible; use auto_impl::auto_impl; use core::error::Error; use primitives::{address, Address, HashMap, StorageKey, StorageValue, B256, U256}; -use state::{Account, AccountInfo, Bytecode}; +use state::{Account, AccountInfo, Bytecode, EvmState}; use std::string::String; /// Address with all `0xff..ff` in it. Used for testing. @@ -69,7 +69,7 @@ pub trait Database { #[auto_impl(&mut, Box)] pub trait DatabaseCommit { /// Commit changes to the database. - fn commit(&mut self, changes: HashMap); + fn commit(&mut self, changes: EvmState); } /// EVM database interface. @@ -138,7 +138,7 @@ impl Database for WrapDatabaseRef { impl DatabaseCommit for WrapDatabaseRef { #[inline] - fn commit(&mut self, changes: HashMap) { + fn commit(&mut self, changes: EvmState) { self.0.commit(changes) } } diff --git a/crates/database/interface/src/try_commit.rs b/crates/database/interface/src/try_commit.rs index 9a7595adcf..435d4c82a8 100644 --- a/crates/database/interface/src/try_commit.rs +++ b/crates/database/interface/src/try_commit.rs @@ -2,7 +2,7 @@ use crate::DatabaseCommit; use core::{convert::Infallible, error::Error, fmt}; use primitives::{Address, HashMap}; -use state::Account; +use state::{Account, EvmState}; use std::sync::Arc; /// EVM database commit interface that can fail. @@ -15,7 +15,7 @@ pub trait TryDatabaseCommit { type Error: Error; /// Attempt to commit changes to the database. - fn try_commit(&mut self, changes: HashMap) -> Result<(), Self::Error>; + fn try_commit(&mut self, changes: EvmState) -> Result<(), Self::Error>; } impl TryDatabaseCommit for Db @@ -25,7 +25,7 @@ where type Error = Infallible; #[inline] - fn try_commit(&mut self, changes: HashMap) -> Result<(), Self::Error> { + fn try_commit(&mut self, changes: EvmState) -> Result<(), Self::Error> { self.commit(changes); Ok(()) } @@ -51,7 +51,7 @@ where type Error = ArcUpgradeError; #[inline] - fn try_commit(&mut self, changes: HashMap) -> Result<(), Self::Error> { + fn try_commit(&mut self, changes: EvmState) -> Result<(), Self::Error> { Arc::get_mut(self) .map(|db| db.commit(changes)) .ok_or(ArcUpgradeError) @@ -67,7 +67,7 @@ mod test { struct MockDb; impl DatabaseCommit for MockDb { - fn commit(&mut self, _changes: HashMap) {} + fn commit(&mut self, _changes: EvmState) {} } #[test] diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index 1437b8c024..89747e6232 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -6,7 +6,7 @@ use database_interface::{ use primitives::{ hash_map::Entry, Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; -use state::{Account, AccountInfo, Bytecode}; +use state::{Account, AccountInfo, Bytecode, EvmState}; use std::vec::Vec; /// A [Database] implementation that stores all state changes in memory. @@ -191,8 +191,8 @@ impl CacheDB { } impl DatabaseCommit for CacheDB { - fn commit(&mut self, changes: HashMap) { - for (address, mut account) in changes { + fn commit(&mut self, changes: EvmState) { + for (mut account, address) in changes.accounts { if !account.is_touched() { continue; } diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index 9105f974cd..b40e257a1f 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -91,7 +91,7 @@ impl CacheState { /// Applies output of revm execution and create account transitions that are used to build BundleState. pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> { let mut transitions = Vec::with_capacity(evm_state.len()); - for (address, account) in evm_state { + for (account, address) in evm_state.accounts.into_iter() { if let Some(transition) = self.apply_account_state(address, account) { transitions.push((address, transition)); } diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 22f8263343..764b6098ef 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -5,7 +5,7 @@ use super::{ use bytecode::Bytecode; use database_interface::{Database, DatabaseCommit, DatabaseRef, EmptyDB}; use primitives::{hash_map, Address, HashMap, StorageKey, StorageValue, B256, BLOCK_HASH_HISTORY}; -use state::{Account, AccountInfo}; +use state::{AccountInfo, EvmState}; use std::{ boxed::Box, collections::{btree_map, BTreeMap}, @@ -310,7 +310,7 @@ impl Database for State { } impl DatabaseCommit for State { - fn commit(&mut self, evm_state: HashMap) { + fn commit(&mut self, evm_state: EvmState) { let transitions = self.cache.apply_evm_state(evm_state); self.apply_transition(transitions); } diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index 45d566dd3d..b8545d65bf 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -19,7 +19,7 @@ use revm::{ Interpreter, InterpreterTypes, }, precompile::{bls12_381_const, bls12_381_utils, bn254, secp256r1, u64_to_address}, - primitives::{bytes, eip7825, Address, Bytes, Log, TxKind, U256}, + primitives::{bytes, eip7825, Address, AddressOrId, Bytes, Log, TxKind, U256}, state::Bytecode, Context, ExecuteEvm, InspectEvm, Inspector, Journal, SystemCallEvm, }; @@ -62,8 +62,8 @@ fn test_deposit_tx() { assert_eq!( output .state - .get(&Address::default()) - .map(|a| a.info.balance), + .get(&AddressOrId::Address(Address::default())) + .map(|a| a.0.info.balance), Some(U256::from(100)) ); compare_or_save_op_testdata("test_deposit_tx.json", &output); @@ -103,7 +103,10 @@ fn test_halted_deposit_tx() { } ); assert_eq!( - output.state.get(&BENCH_CALLER).map(|a| a.info.balance), + output + .state + .get(&BENCH_CALLER.into()) + .map(|a| a.0.info.balance), Some(U256::from(100) + BENCH_CALLER_BALANCE) ); @@ -1137,6 +1140,6 @@ fn test_system_call() { let _ = evm.system_call_one(BENCH_TARGET, bytes!("0x0001")); let state = evm.finalize(); - assert!(state.get(&SYSTEM_ADDRESS).is_none()); - assert!(state.get(&BENCH_TARGET).unwrap().is_touched()); + assert!(state.get(&SYSTEM_ADDRESS.into()).is_none()); + assert!(state.get(&BENCH_TARGET.into()).unwrap().0.is_touched()); } diff --git a/crates/handler/src/mainnet_builder.rs b/crates/handler/src/mainnet_builder.rs index 4e53287c93..bb9abc50fe 100644 --- a/crates/handler/src/mainnet_builder.rs +++ b/crates/handler/src/mainnet_builder.rs @@ -119,11 +119,12 @@ mod test { .unwrap() .state; - let auth_acc = state.get(&signer.address()).unwrap(); - assert_eq!(auth_acc.info.code, Some(Bytecode::new_eip7702(FFADDRESS))); - assert_eq!(auth_acc.info.nonce, 1); + let auth_acc = state.get(&signer.address().into()).unwrap(); + assert_eq!(auth_acc.0.info.code, Some(Bytecode::new_eip7702(FFADDRESS))); + assert_eq!(auth_acc.0.info.nonce, 1); assert_eq!( auth_acc + .0 .storage .get(&StorageKey::from(1)) .unwrap() diff --git a/crates/handler/src/system_call.rs b/crates/handler/src/system_call.rs index d4ce748ee5..f73a1f1b05 100644 --- a/crates/handler/src/system_call.rs +++ b/crates/handler/src/system_call.rs @@ -315,7 +315,11 @@ mod tests { // only system contract is updated and present assert_eq!(output.state.len(), 1); assert_eq!( - output.state[&HISTORY_STORAGE_ADDRESS] + output + .state + .get(&HISTORY_STORAGE_ADDRESS.into()) + .unwrap() + .0 .storage .get(&StorageKey::from(0)) .map(|slot| slot.present_value) diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index a1c40c8214..78d7d9f8a3 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -5,7 +5,7 @@ use interpreter::{ InterpreterTypes, }; use primitives::{Address, Log, U256}; -use state::EvmStateNew; +use state::EvmState; /// EVM hooks into execution. /// @@ -182,10 +182,10 @@ pub trait JournalExt { fn journal(&self) -> &[JournalEntry]; /// Return the current Journaled state. - fn evm_state(&self) -> &EvmStateNew; + fn evm_state(&self) -> &EvmState; /// Return the mutable current Journaled state. - fn evm_state_mut(&mut self) -> &mut EvmStateNew; + fn evm_state_mut(&mut self) -> &mut EvmState; } impl JournalExt for Journal { @@ -200,12 +200,12 @@ impl JournalExt for Journal { } #[inline] - fn evm_state(&self) -> &EvmStateNew { + fn evm_state(&self) -> &EvmState { &self.state_new } #[inline] - fn evm_state_mut(&mut self) -> &mut EvmStateNew { + fn evm_state_mut(&mut self) -> &mut EvmState { &mut self.state_new } } diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 020ee0337f..ce64646ea8 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -12,4 +12,4 @@ pub use account_info::AccountInfo; pub use bytecode::{self, Bytecode}; pub use primitives; pub use storage::EvmStorageSlot; -pub use types::{EvmState, EvmStateNew, EvmStorage, TransientStorage}; +pub use types::{EvmState, EvmStorage, TransientStorage}; diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index b0791bdb4d..7c9a4aecee 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -3,9 +3,6 @@ use primitives::{ map::Entry, AccountId, Address, AddressAndId, AddressOrId, HashMap, StorageKey, StorageValue, }; -/// EVM State is a mapping from addresses to accounts. -pub type EvmState = HashMap; - /// Structure used for EIP-1153 transient storage pub type TransientStorage = HashMap<(AccountId, StorageKey), StorageValue>; @@ -15,7 +12,7 @@ pub type EvmStorage = HashMap; /// EVM State with internal account management. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct EvmStateNew { +pub struct EvmState { /// Index of accounts. pub index: HashMap, /// Accounts. @@ -23,7 +20,7 @@ pub struct EvmStateNew { pub accounts: Vec<(Account, Address)>, } -impl EvmStateNew { +impl EvmState { /// Create a new empty state. pub fn new() -> Self { Self { @@ -159,15 +156,15 @@ impl EvmStateNew { } } -impl Default for EvmStateNew { +impl Default for EvmState { fn default() -> Self { Self::new() } } -impl From> for EvmStateNew { +impl From> for EvmState { fn from(map: HashMap) -> Self { - let mut state = EvmStateNew::new(); + let mut state = EvmState::new(); for (address, account) in map { state.insert(address, account); } From 7a18695a73b8d496888cf76ec6d92252fb94bc3d Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Aug 2025 18:47:23 +0200 Subject: [PATCH 08/37] inline never some functions --- crates/context/src/journal.rs | 2 +- crates/context/src/journal/inner.rs | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 1e33feea31..56a96f17cd 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -188,7 +188,7 @@ impl JournalTr for Journal { self.inner.depth } - #[inline] + #[inline(never)] fn warm_account_and_storage( &mut self, address: Address, diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a959d76cbe..ed37b25ac7 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -155,7 +155,6 @@ impl JournalInner { /// /// Note: Precompile addresses and spec are preserved and initial state of /// warm_preloaded_addresses will contain precompiles addresses. - #[inline] pub fn finalize(&mut self) -> EvmState { // Clears all field from JournalInner. Doing it this way to avoid // missing any field. @@ -288,7 +287,7 @@ impl JournalInner { /// Increments the balance of the account. /// /// Mark account as touched. - #[inline] + #[inline(never)] pub fn balance_incr( &mut self, db: &mut DB, @@ -320,7 +319,7 @@ impl JournalInner { } /// Transfers balance from two accounts. Returns error if sender balance is not enough. - #[inline] + #[inline(never)] pub fn transfer( &mut self, db: &mut DB, @@ -379,7 +378,7 @@ impl JournalInner { /// /// Panics if the caller is not loaded inside the EVM state. /// This should have been done inside `create_inner`. - #[inline] + #[inline(never)] pub fn create_account_checkpoint( &mut self, caller_or_id: AddressOrId, @@ -495,7 +494,7 @@ impl JournalInner { /// * /// * /// * - #[inline] + #[inline(never)] pub fn selfdestruct( &mut self, db: &mut DB, @@ -570,7 +569,7 @@ impl JournalInner { } /// Loads account into memory. return if it is cold or warm accessed - #[inline] + #[inline(never)] pub fn load_account( &mut self, db: &mut DB, @@ -586,7 +585,7 @@ impl JournalInner { /// /// Returns information about the account (If it is empty or cold loaded) and if present the information /// about the delegated account (If it is cold loaded). - #[inline] + #[inline(never)] pub fn load_account_delegated( &mut self, db: &mut DB, @@ -623,7 +622,7 @@ impl JournalInner { /// /// In case of EIP-7702 delegated account will not be loaded, /// [`Self::load_account_delegated`] should be used instead. - #[inline] + #[inline(never)] pub fn load_code( &mut self, db: &mut DB, @@ -633,7 +632,7 @@ impl JournalInner { } /// Loads account. If account is already loaded it will be marked as warm. - #[inline(never)] + #[inline(always)] pub fn load_account_optional( &mut self, db: &mut DB, From 3b804f383eb21ad8585150ea59ce00bc206a9e18 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Aug 2025 19:00:37 +0200 Subject: [PATCH 09/37] Revert "inline never some functions" This reverts commit 7a18695a73b8d496888cf76ec6d92252fb94bc3d. --- crates/context/src/journal.rs | 2 +- crates/context/src/journal/inner.rs | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 56a96f17cd..1e33feea31 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -188,7 +188,7 @@ impl JournalTr for Journal { self.inner.depth } - #[inline(never)] + #[inline] fn warm_account_and_storage( &mut self, address: Address, diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index ed37b25ac7..a959d76cbe 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -155,6 +155,7 @@ impl JournalInner { /// /// Note: Precompile addresses and spec are preserved and initial state of /// warm_preloaded_addresses will contain precompiles addresses. + #[inline] pub fn finalize(&mut self) -> EvmState { // Clears all field from JournalInner. Doing it this way to avoid // missing any field. @@ -287,7 +288,7 @@ impl JournalInner { /// Increments the balance of the account. /// /// Mark account as touched. - #[inline(never)] + #[inline] pub fn balance_incr( &mut self, db: &mut DB, @@ -319,7 +320,7 @@ impl JournalInner { } /// Transfers balance from two accounts. Returns error if sender balance is not enough. - #[inline(never)] + #[inline] pub fn transfer( &mut self, db: &mut DB, @@ -378,7 +379,7 @@ impl JournalInner { /// /// Panics if the caller is not loaded inside the EVM state. /// This should have been done inside `create_inner`. - #[inline(never)] + #[inline] pub fn create_account_checkpoint( &mut self, caller_or_id: AddressOrId, @@ -494,7 +495,7 @@ impl JournalInner { /// * /// * /// * - #[inline(never)] + #[inline] pub fn selfdestruct( &mut self, db: &mut DB, @@ -569,7 +570,7 @@ impl JournalInner { } /// Loads account into memory. return if it is cold or warm accessed - #[inline(never)] + #[inline] pub fn load_account( &mut self, db: &mut DB, @@ -585,7 +586,7 @@ impl JournalInner { /// /// Returns information about the account (If it is empty or cold loaded) and if present the information /// about the delegated account (If it is cold loaded). - #[inline(never)] + #[inline] pub fn load_account_delegated( &mut self, db: &mut DB, @@ -622,7 +623,7 @@ impl JournalInner { /// /// In case of EIP-7702 delegated account will not be loaded, /// [`Self::load_account_delegated`] should be used instead. - #[inline(never)] + #[inline] pub fn load_code( &mut self, db: &mut DB, @@ -632,7 +633,7 @@ impl JournalInner { } /// Loads account. If account is already loaded it will be marked as warm. - #[inline(always)] + #[inline(never)] pub fn load_account_optional( &mut self, db: &mut DB, From 695d449fd1861ce2838c99ca48fce31cfce156f9 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 00:18:11 +0200 Subject: [PATCH 10/37] remove boxes over frame input --- bins/revme/src/cmd/bench/transfer.rs | 4 +- crates/context/src/journal/inner.rs | 2 +- crates/handler/src/execution.rs | 9 +- crates/handler/src/frame.rs | 4 +- crates/handler/src/validation.rs | 2 + .../interpreter/src/instructions/contract.rs | 100 ++++++++---------- crates/interpreter/src/interpreter_action.rs | 4 +- crates/state/src/types.rs | 4 +- 8 files changed, 62 insertions(+), 67 deletions(-) diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index cccbe33f88..5de71107c5 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -53,7 +53,7 @@ pub fn run(criterion: &mut Criterion) { // drop the journal let _ = evm.finalize(); - evm.modify_cfg(|cfg| cfg.disable_nonce_check = false); + // evm.modify_cfg(|cfg| cfg.disable_nonce_check = false); - criterion.bench_function("transfer_finalize", |b| b.iter(|| evm.replay().unwrap())); + // criterion.bench_function("transfer_finalize", |b| b.iter(|| evm.replay().unwrap())); } diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a959d76cbe..43970cb79e 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -829,7 +829,7 @@ impl JournalInner { } /// Loads storage slot with account. -#[inline] +#[inline(never)] pub fn sload_with_account( account: &mut Account, db: &mut DB, diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index 34602b4732..d1a4aeb451 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -5,6 +5,7 @@ use primitives::{AddressAndId, Bytes, U256}; use std::boxed::Box; /// Creates the first [`FrameInput`] from the transaction, spec and gas limit. +#[inline] pub fn create_init_frame( is_call: bool, caller: AddressAndId, @@ -14,7 +15,7 @@ pub fn create_init_frame( gas_limit: u64, ) -> FrameInput { if is_call { - FrameInput::Call(Box::new(CallInputs { + FrameInput::Call(CallInputs { input: CallInput::Bytes(input), gas_limit, target_address: target, @@ -24,14 +25,14 @@ pub fn create_init_frame( scheme: CallScheme::Call, is_static: false, return_memory_offset: 0..0, - })) + }) } else { - FrameInput::Create(Box::new(CreateInputs { + FrameInput::Create(CreateInputs { caller, scheme: CreateScheme::Create, value, init_code: input, gas_limit, - })) + }) } } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 1eb0ab3745..ad01409d5d 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -143,7 +143,7 @@ impl EthFrame { precompiles: &mut PRECOMPILES, depth: usize, memory: SharedMemory, - inputs: Box, + inputs: CallInputs, ) -> Result, ERROR> { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -309,7 +309,7 @@ impl EthFrame { context: &mut CTX, depth: usize, memory: SharedMemory, - inputs: Box, + inputs: CreateInputs, ) -> Result, ERROR> { let spec = context.cfg().spec().into(); let return_error = |e| { diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index 241022bf9f..ca115c0699 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -8,6 +8,7 @@ use interpreter::gas::{self, InitialAndFloorGas}; use primitives::{eip4844, hardfork::SpecId, B256}; /// Validates the execution environment including block and transaction parameters. +#[inline] pub fn validate_env + From>( context: CTX, ) -> Result<(), ERROR> { @@ -218,6 +219,7 @@ pub fn validate_tx_env( } /// Validate initial transaction gas. +#[inline] pub fn validate_initial_tx_gas( tx: impl Transaction, spec: SpecId, diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 53cd798364..396509e95d 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -91,7 +91,7 @@ pub fn create( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Create(Box::new( + .set_action(InterpreterAction::NewFrame(FrameInput::Create( CreateInputs { caller: context.interpreter.input.target_address(), scheme, @@ -99,7 +99,7 @@ pub fn create( init_code: code, gas_limit, }, - )))); + ))); } /// Implements the CALL instruction. @@ -155,19 +155,17 @@ pub fn call(context: InstructionContex context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( - CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: to, - caller: context.interpreter.input.target_address(), - bytecode_address: to, - value: CallValue::Transfer(value), - scheme: CallScheme::Call, - is_static: context.interpreter.runtime_flag.is_static(), - return_memory_offset, - }, - )))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: to, + caller: context.interpreter.input.target_address(), + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::Call, + is_static: context.interpreter.runtime_flag.is_static(), + return_memory_offset, + }))); } /// Implements the CALLCODE instruction. @@ -214,19 +212,17 @@ pub fn call_code( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( - CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: context.interpreter.input.target_address(), - caller: context.interpreter.input.target_address(), - bytecode_address: to, - value: CallValue::Transfer(value), - scheme: CallScheme::CallCode, - is_static: context.interpreter.runtime_flag.is_static(), - return_memory_offset, - }, - )))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: context.interpreter.input.target_address(), + caller: context.interpreter.input.target_address(), + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::CallCode, + is_static: context.interpreter.runtime_flag.is_static(), + return_memory_offset, + }))); } /// Implements the DELEGATECALL instruction. @@ -266,19 +262,17 @@ pub fn delegate_call( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( - CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: context.interpreter.input.target_address(), - caller: context.interpreter.input.caller_address(), - bytecode_address: to, - value: CallValue::Apparent(context.interpreter.input.call_value()), - scheme: CallScheme::DelegateCall, - is_static: context.interpreter.runtime_flag.is_static(), - return_memory_offset, - }, - )))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: context.interpreter.input.target_address(), + caller: context.interpreter.input.caller_address(), + bytecode_address: to, + value: CallValue::Apparent(context.interpreter.input.call_value()), + scheme: CallScheme::DelegateCall, + is_static: context.interpreter.runtime_flag.is_static(), + return_memory_offset, + }))); } /// Implements the STATICCALL instruction. @@ -317,17 +311,15 @@ pub fn static_call( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( - CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: to, - caller: context.interpreter.input.target_address(), - bytecode_address: to, - value: CallValue::Transfer(U256::ZERO), - scheme: CallScheme::StaticCall, - is_static: true, - return_memory_offset, - }, - )))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: to, + caller: context.interpreter.input.target_address(), + bytecode_address: to, + value: CallValue::Transfer(U256::ZERO), + scheme: CallScheme::StaticCall, + is_static: true, + return_memory_offset, + }))); } diff --git a/crates/interpreter/src/interpreter_action.rs b/crates/interpreter/src/interpreter_action.rs index 83cf29741f..22ae962eba 100644 --- a/crates/interpreter/src/interpreter_action.rs +++ b/crates/interpreter/src/interpreter_action.rs @@ -19,9 +19,9 @@ pub enum FrameInput { /// No input data (empty frame) Empty, /// `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL` instruction called. - Call(Box), + Call(CallInputs), /// `CREATE` or `CREATE2` instruction called. - Create(Box), + Create(CreateInputs), } /// Initialization data for creating a new execution frame. diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 7c9a4aecee..cd266d21fd 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -145,11 +145,11 @@ impl EvmState { Ok((account, address_and_id)) } Entry::Vacant(entry) => { - let account = fetch(address)?; let id = self.accounts.len(); entry.insert(id); - self.accounts.push((account, address)); let address_and_id = AddressAndId::new(address, id); + let account = fetch(address)?; + self.accounts.push((account, address)); Ok((&mut self.accounts.last_mut().unwrap().0, address_and_id)) } } From c4bee08967e70992285fb3c3727004aa7eddf930 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 00:24:08 +0200 Subject: [PATCH 11/37] use caller id for reimbursment --- crates/handler/src/post_execution.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index ca8f1aff69..18dc4c15d3 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -1,4 +1,5 @@ use crate::FrameResult; +use context::journal; use context_interface::{ journaled_state::JournalTr, result::{ExecutionResult, HaltReasonTr}, @@ -36,12 +37,12 @@ pub fn reimburse_caller( ) -> Result<(), ::Error> { let basefee = context.block().basefee() as u128; // TODO save AccountId somewhere so we can access it here. - let caller = context.tx().caller().into(); + let caller = context.journal().caller_address_id().unwrap(); let effective_gas_price = context.tx().effective_gas_price(basefee); // Return balance of not spend gas. context.journal_mut().balance_incr( - caller, + caller.to_id(), U256::from( effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128), ) + additional_refund, From 28d7e9e59df97448c5f0bca62b193d1dde3f5398 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 01:22:27 +0200 Subject: [PATCH 12/37] Revert "remove boxes over frame input" This reverts commit 695d449fd1861ce2838c99ca48fce31cfce156f9. --- bins/revme/src/cmd/bench/transfer.rs | 4 +- crates/context/src/journal/inner.rs | 2 +- crates/handler/src/execution.rs | 9 +- crates/handler/src/frame.rs | 4 +- crates/handler/src/validation.rs | 2 - .../interpreter/src/instructions/contract.rs | 100 ++++++++++-------- crates/interpreter/src/interpreter_action.rs | 4 +- crates/state/src/types.rs | 4 +- 8 files changed, 67 insertions(+), 62 deletions(-) diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index 5de71107c5..cccbe33f88 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -53,7 +53,7 @@ pub fn run(criterion: &mut Criterion) { // drop the journal let _ = evm.finalize(); - // evm.modify_cfg(|cfg| cfg.disable_nonce_check = false); + evm.modify_cfg(|cfg| cfg.disable_nonce_check = false); - // criterion.bench_function("transfer_finalize", |b| b.iter(|| evm.replay().unwrap())); + criterion.bench_function("transfer_finalize", |b| b.iter(|| evm.replay().unwrap())); } diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 43970cb79e..a959d76cbe 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -829,7 +829,7 @@ impl JournalInner { } /// Loads storage slot with account. -#[inline(never)] +#[inline] pub fn sload_with_account( account: &mut Account, db: &mut DB, diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index d1a4aeb451..34602b4732 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -5,7 +5,6 @@ use primitives::{AddressAndId, Bytes, U256}; use std::boxed::Box; /// Creates the first [`FrameInput`] from the transaction, spec and gas limit. -#[inline] pub fn create_init_frame( is_call: bool, caller: AddressAndId, @@ -15,7 +14,7 @@ pub fn create_init_frame( gas_limit: u64, ) -> FrameInput { if is_call { - FrameInput::Call(CallInputs { + FrameInput::Call(Box::new(CallInputs { input: CallInput::Bytes(input), gas_limit, target_address: target, @@ -25,14 +24,14 @@ pub fn create_init_frame( scheme: CallScheme::Call, is_static: false, return_memory_offset: 0..0, - }) + })) } else { - FrameInput::Create(CreateInputs { + FrameInput::Create(Box::new(CreateInputs { caller, scheme: CreateScheme::Create, value, init_code: input, gas_limit, - }) + })) } } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index ad01409d5d..1eb0ab3745 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -143,7 +143,7 @@ impl EthFrame { precompiles: &mut PRECOMPILES, depth: usize, memory: SharedMemory, - inputs: CallInputs, + inputs: Box, ) -> Result, ERROR> { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -309,7 +309,7 @@ impl EthFrame { context: &mut CTX, depth: usize, memory: SharedMemory, - inputs: CreateInputs, + inputs: Box, ) -> Result, ERROR> { let spec = context.cfg().spec().into(); let return_error = |e| { diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index ca115c0699..241022bf9f 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -8,7 +8,6 @@ use interpreter::gas::{self, InitialAndFloorGas}; use primitives::{eip4844, hardfork::SpecId, B256}; /// Validates the execution environment including block and transaction parameters. -#[inline] pub fn validate_env + From>( context: CTX, ) -> Result<(), ERROR> { @@ -219,7 +218,6 @@ pub fn validate_tx_env( } /// Validate initial transaction gas. -#[inline] pub fn validate_initial_tx_gas( tx: impl Transaction, spec: SpecId, diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 396509e95d..53cd798364 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -91,7 +91,7 @@ pub fn create( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Create( + .set_action(InterpreterAction::NewFrame(FrameInput::Create(Box::new( CreateInputs { caller: context.interpreter.input.target_address(), scheme, @@ -99,7 +99,7 @@ pub fn create( init_code: code, gas_limit, }, - ))); + )))); } /// Implements the CALL instruction. @@ -155,17 +155,19 @@ pub fn call(context: InstructionContex context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: to, - caller: context.interpreter.input.target_address(), - bytecode_address: to, - value: CallValue::Transfer(value), - scheme: CallScheme::Call, - is_static: context.interpreter.runtime_flag.is_static(), - return_memory_offset, - }))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( + CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: to, + caller: context.interpreter.input.target_address(), + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::Call, + is_static: context.interpreter.runtime_flag.is_static(), + return_memory_offset, + }, + )))); } /// Implements the CALLCODE instruction. @@ -212,17 +214,19 @@ pub fn call_code( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: context.interpreter.input.target_address(), - caller: context.interpreter.input.target_address(), - bytecode_address: to, - value: CallValue::Transfer(value), - scheme: CallScheme::CallCode, - is_static: context.interpreter.runtime_flag.is_static(), - return_memory_offset, - }))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( + CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: context.interpreter.input.target_address(), + caller: context.interpreter.input.target_address(), + bytecode_address: to, + value: CallValue::Transfer(value), + scheme: CallScheme::CallCode, + is_static: context.interpreter.runtime_flag.is_static(), + return_memory_offset, + }, + )))); } /// Implements the DELEGATECALL instruction. @@ -262,17 +266,19 @@ pub fn delegate_call( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: context.interpreter.input.target_address(), - caller: context.interpreter.input.caller_address(), - bytecode_address: to, - value: CallValue::Apparent(context.interpreter.input.call_value()), - scheme: CallScheme::DelegateCall, - is_static: context.interpreter.runtime_flag.is_static(), - return_memory_offset, - }))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( + CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: context.interpreter.input.target_address(), + caller: context.interpreter.input.caller_address(), + bytecode_address: to, + value: CallValue::Apparent(context.interpreter.input.call_value()), + scheme: CallScheme::DelegateCall, + is_static: context.interpreter.runtime_flag.is_static(), + return_memory_offset, + }, + )))); } /// Implements the STATICCALL instruction. @@ -311,15 +317,17 @@ pub fn static_call( context .interpreter .bytecode - .set_action(InterpreterAction::NewFrame(FrameInput::Call(CallInputs { - input: CallInput::SharedBuffer(input), - gas_limit, - target_address: to, - caller: context.interpreter.input.target_address(), - bytecode_address: to, - value: CallValue::Transfer(U256::ZERO), - scheme: CallScheme::StaticCall, - is_static: true, - return_memory_offset, - }))); + .set_action(InterpreterAction::NewFrame(FrameInput::Call(Box::new( + CallInputs { + input: CallInput::SharedBuffer(input), + gas_limit, + target_address: to, + caller: context.interpreter.input.target_address(), + bytecode_address: to, + value: CallValue::Transfer(U256::ZERO), + scheme: CallScheme::StaticCall, + is_static: true, + return_memory_offset, + }, + )))); } diff --git a/crates/interpreter/src/interpreter_action.rs b/crates/interpreter/src/interpreter_action.rs index 22ae962eba..83cf29741f 100644 --- a/crates/interpreter/src/interpreter_action.rs +++ b/crates/interpreter/src/interpreter_action.rs @@ -19,9 +19,9 @@ pub enum FrameInput { /// No input data (empty frame) Empty, /// `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL` instruction called. - Call(CallInputs), + Call(Box), /// `CREATE` or `CREATE2` instruction called. - Create(CreateInputs), + Create(Box), } /// Initialization data for creating a new execution frame. diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index cd266d21fd..7c9a4aecee 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -145,11 +145,11 @@ impl EvmState { Ok((account, address_and_id)) } Entry::Vacant(entry) => { + let account = fetch(address)?; let id = self.accounts.len(); entry.insert(id); - let address_and_id = AddressAndId::new(address, id); - let account = fetch(address)?; self.accounts.push((account, address)); + let address_and_id = AddressAndId::new(address, id); Ok((&mut self.accounts.last_mut().unwrap().0, address_and_id)) } } From 36ab3c9ca6e967c2b91a1f5f09fe46cbda48941c Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 02:18:40 +0200 Subject: [PATCH 13/37] simplify transfer of value --- .../context/interface/src/journaled_state.rs | 21 ++++--- crates/context/src/journal.rs | 23 +++++--- crates/context/src/journal/inner.rs | 41 ++++++------- crates/handler/src/frame.rs | 58 +++++++++++-------- crates/interpreter/src/gas/calc.rs | 4 +- crates/state/src/account.rs | 9 +-- crates/state/src/storage.rs | 10 +--- 7 files changed, 84 insertions(+), 82 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 6eb5773e03..f7ed9df1a4 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -3,8 +3,8 @@ use crate::context::{SStoreResult, SelfDestructResult}; use core::ops::{Deref, DerefMut}; use database_interface::Database; use primitives::{ - hardfork::SpecId, Address, AddressAndId, AddressOrId, Bytes, HashSet, Log, StorageKey, - StorageValue, B256, U256, + hardfork::SpecId, AccountId, Address, AddressAndId, AddressOrId, Bytes, HashSet, Log, + StorageKey, StorageValue, B256, U256, }; use state::{Account, Bytecode}; use std::vec::Vec; @@ -94,12 +94,7 @@ pub trait JournalTr { fn touch_account(&mut self, address_or_id: AddressOrId); /// Transfers the balance from one account to another. - fn transfer( - &mut self, - from: AddressOrId, - to: AddressOrId, - balance: U256, - ) -> Result, ::Error>; + fn transfer(&mut self, from: AccountId, to: AccountId, balance: U256) -> Option; /// Increments the balance of the account. fn caller_accounting_journal_entry( @@ -131,6 +126,12 @@ pub trait JournalTr { address_or_id: AddressOrId, ) -> Result, ::Error>; + /// Returns the account by id. + fn get_account_mut(&mut self, account_id: AccountId) -> Option<&mut Account>; + + /// Fast fetch the account by id. + fn get_account(&mut self, account_id: AccountId) -> Option<&Account>; + /// Sets the caller id. fn set_caller_address_id(&mut self, id: AddressAndId); @@ -297,12 +298,10 @@ impl StateLoad { #[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccountLoad { - /// Does account have delegate code and delegated account is cold loaded - pub is_delegate_account_cold: Option, /// Is account empty, if `true` account is not created pub is_empty: bool, /// Account address and id. pub address_and_id: AddressAndId, - /// delegated account address, + /// Does account have delegate code and delegated account is cold loaded pub delegated_account_address: Option>, } diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 1e33feea31..951f8cd050 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -17,8 +17,8 @@ use context_interface::{ use core::ops::{Deref, DerefMut}; use database_interface::Database; use primitives::{ - hardfork::SpecId, Address, AddressAndId, AddressOrId, HashSet, Log, StorageKey, StorageValue, - B256, U256, + hardfork::SpecId, AccountId, Address, AddressAndId, AddressOrId, HashSet, Log, StorageKey, + StorageValue, B256, U256, }; use state::{Account, EvmState}; use std::vec::Vec; @@ -182,6 +182,16 @@ impl JournalTr for Journal { self.inner.warm_addresses.precompiles() } + #[inline] + fn get_account_mut(&mut self, account_id: AccountId) -> Option<&mut Account> { + self.inner.state().get_by_id_mut(account_id).map(|(a, _)| a) + } + + #[inline] + fn get_account(&mut self, account_id: AccountId) -> Option<&Account> { + self.inner.state().get_by_id(account_id).map(|(a, _)| a) + } + /// Returns call depth. #[inline] fn depth(&self) -> usize { @@ -210,13 +220,8 @@ impl JournalTr for Journal { } #[inline] - fn transfer( - &mut self, - from: AddressOrId, - to: AddressOrId, - balance: U256, - ) -> Result, DB::Error> { - self.inner.transfer(&mut self.database, from, to, balance) + fn transfer(&mut self, from: AccountId, to: AccountId, balance: U256) -> Option { + self.inner.transfer(from, to, balance) } #[inline] diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a959d76cbe..31b24a6a56 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -12,7 +12,7 @@ use database_interface::Database; use primitives::{ hardfork::SpecId::{self, *}, hash_map::Entry, - AccountId, Address, AddressAndId, AddressOrId, HashMap, Log, StorageKey, StorageValue, B256, + AccountId, Address, AddressAndId, AddressOrId, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; use state::{Account, EvmState, EvmStorageSlot, TransientStorage}; @@ -321,47 +321,42 @@ impl JournalInner { /// Transfers balance from two accounts. Returns error if sender balance is not enough. #[inline] - pub fn transfer( + pub fn transfer( &mut self, - db: &mut DB, - from: AddressOrId, - to: AddressOrId, + from: AccountId, + to: AccountId, balance: U256, - ) -> Result, DB::Error> { + ) -> Option { if balance.is_zero() { - self.load_account(db, to)?; - let (to_account, to) = self.state_new.get_mut(to).unwrap(); - Self::touch_account(&mut self.journal, to.id(), to_account); - return Ok(None); + let to_account = self.state_new.get_by_id_mut(to).unwrap().0; + Self::touch_account(&mut self.journal, to, to_account); + return None; } - // load accounts - let (_, to) = self.load_account(db, to)?.data; - let (_, from) = self.load_account(db, from)?.data; // sub balance from - let (from_account, from) = self.state_new.get_mut(AddressOrId::Id(from.id())).unwrap(); - Self::touch_account(&mut self.journal, from.id(), from_account); + let (from_account, _) = self.state_new.get_by_id_mut(from).unwrap(); + Self::touch_account(&mut self.journal, from, from_account); let from_balance = &mut from_account.info.balance; let Some(from_balance_decr) = from_balance.checked_sub(balance) else { - return Ok(Some(TransferError::OutOfFunds)); + return Some(TransferError::OutOfFunds); }; *from_balance = from_balance_decr; // add balance to - let (to_account, to) = self.state_new.get_mut(AddressOrId::Id(to.id())).unwrap(); - Self::touch_account(&mut self.journal, to.id(), to_account); + let (to_account, _) = self.state_new.get_by_id_mut(to).unwrap(); + Self::touch_account(&mut self.journal, to, to_account); let to_balance = &mut to_account.info.balance; let Some(to_balance_incr) = to_balance.checked_add(balance) else { - return Ok(Some(TransferError::OverflowPayment)); + return Some(TransferError::OverflowPayment); }; *to_balance = to_balance_incr; // Overflow of U256 balance is not possible to happen on mainnet. We don't bother to return funds from from_acc. self.journal - .push(ENTRY::balance_transfer(from.id(), to.id(), balance)); + .push(ENTRY::balance_transfer(from, to, balance)); - Ok(None) + None } /// Creates account or returns false if collision is detected. @@ -601,7 +596,6 @@ impl JournalInner { AccountLoad { address_and_id: account.1, delegated_account_address: None, - is_delegate_account_cold: None, is_empty, }, account.is_cold, @@ -611,7 +605,8 @@ impl JournalInner { if let Some(Bytecode::Eip7702(code)) = &account.0.info.code { let address = code.address(); let delegate_account = self.load_account(db, AddressOrId::Address(address))?; - account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold); + account_load.data.delegated_account_address = + Some(StateLoad::new(delegate_account.1, delegate_account.is_cold)); } Ok(account_load) diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 1eb0ab3745..4933a7f1e2 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -163,9 +163,10 @@ impl EthFrame { } // Make account warm and loaded. - let _ = ctx + let acc_load = ctx .journal_mut() - .load_account_delegated(inputs.bytecode_address.to_id())?; + .load_account_delegated(inputs.bytecode_address.to_id())? + .data; // Create subroutine checkpoint let checkpoint = ctx.journal_mut().checkpoint(); @@ -174,11 +175,10 @@ impl EthFrame { if let CallValue::Transfer(value) = inputs.value { // Transfer value from caller to called account // Target will get touched even if balance transferred is zero. - if let Some(i) = ctx.journal_mut().transfer( - inputs.caller.to_id(), - inputs.target_address.to_id(), - value, - )? { + if let Some(i) = + ctx.journal_mut() + .transfer(inputs.caller.id(), inputs.target_address.id(), value) + { ctx.journal_mut().checkpoint_revert(checkpoint); return return_result(i.into()); } @@ -215,22 +215,34 @@ impl EthFrame { }))); } - let account = ctx - .journal_mut() - .load_account_code(inputs.bytecode_address.to_id())?; - - let mut code_hash = account.0.info.code_hash(); - let mut bytecode = account.0.info.code.clone().unwrap_or_default(); - - if let Bytecode::Eip7702(eip7702_bytecode) = bytecode { - let account = &ctx - .journal_mut() - .load_account_code(eip7702_bytecode.delegated_address.into())? - .0 - .info; - bytecode = account.code.clone().unwrap_or_default(); - code_hash = account.code_hash(); - } + // let account = ctx + // .journal_mut() + // .load_account_code(inputs.bytecode_address.to_id())?; + + // let mut bytecode = account.0.info.code.clone().unwrap_or_default(); + + let account = if let Some(delegated_acc) = acc_load.delegated_account_address { + ctx.journal_mut() + .get_account(delegated_acc.id()) + .expect("delegated account should be loaded") + } else { + ctx.journal_mut() + .get_account(acc_load.address_and_id.id()) + .expect("account should be loaded") + }; + + let code_hash = account.info.code_hash(); + let bytecode = account.info.code.clone().unwrap_or_default(); + + // if let Bytecode::Eip7702(eip7702_bytecode) = bytecode { + // let account = &ctx + // .journal_mut() + // .load_account_code(eip7702_bytecode.delegated_address.into())? + // .0 + // .info; + // bytecode = account.code.clone().unwrap_or_default(); + // code_hash = account.code_hash(); + // } // Returns success if bytecode is empty. if bytecode.is_empty() { diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 08ec9c0f07..e570090299 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -327,8 +327,8 @@ pub const fn warm_cold_cost(is_cold: bool) -> u64 { #[inline] pub const fn warm_cold_cost_with_delegation(load: StateLoad) -> u64 { let mut gas = warm_cold_cost(load.is_cold); - if let Some(is_cold) = load.data.is_delegate_account_cold { - gas += warm_cold_cost(is_cold); + if let Some(delegated_acc) = load.data.delegated_account_address { + gas += warm_cold_cost(delegated_acc.is_cold); } gas } diff --git a/crates/state/src/account.rs b/crates/state/src/account.rs index 70b8683c11..3464c37e28 100644 --- a/crates/state/src/account.rs +++ b/crates/state/src/account.rs @@ -98,16 +98,11 @@ impl Account { #[inline] pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { let same_id = self.transaction_id == transaction_id; + self.transaction_id = transaction_id; let is_cold = self.status.contains(AccountStatus::Cold); - self.status -= AccountStatus::Cold; - self.transaction_id = transaction_id; - - if !same_id { - return true; - } - is_cold + (same_id && is_cold) || !same_id } /// Is account locally created diff --git a/crates/state/src/storage.rs b/crates/state/src/storage.rs index 3ea71a6635..490e496cd1 100644 --- a/crates/state/src/storage.rs +++ b/crates/state/src/storage.rs @@ -71,13 +71,9 @@ impl EvmStorageSlot { pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { let same_id = self.transaction_id == transaction_id; self.transaction_id = transaction_id; - let was_cold = core::mem::replace(&mut self.is_cold, false); - - if same_id { - // only if transaction id is same we are returning was_cold. - return was_cold; - } - true + let was_cold = core::mem::take(&mut self.is_cold); + // only if transaction id is same we are returning was_cold. + (same_id && was_cold) || !same_id } } From 626f3e8a3fa8aa74787533ae20cfeaf4bd893d11 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 02:44:40 +0200 Subject: [PATCH 14/37] load caller by id --- crates/context/interface/src/journaled_state.rs | 3 +++ crates/context/src/journal.rs | 5 +++++ crates/context/src/journal/inner.rs | 17 +++++++++++++++++ crates/handler/src/post_execution.rs | 8 ++++---- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index f7ed9df1a4..d9b92d5303 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -111,6 +111,9 @@ pub trait JournalTr { balance: U256, ) -> Result::Error>; + /// Increments the balance of the account. + fn balance_incr_by_id(&mut self, account_id: AccountId, balance: U256); + /// Increments the nonce of the account. fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId); diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 951f8cd050..74e4d306b2 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -251,6 +251,11 @@ impl JournalTr for Journal { .balance_incr(&mut self.database, address_or_id, balance) } + #[inline] + fn balance_incr_by_id(&mut self, account_id: AccountId, balance: U256) { + self.inner.balance_incr_by_id(account_id, balance) + } + /// Increments the nonce of the account. #[inline] fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId) { diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 31b24a6a56..1039b84f77 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -311,6 +311,23 @@ impl JournalInner { Ok(address) } + #[inline] + pub fn balance_incr_by_id(&mut self, account_id: AccountId, balance: U256) { + let account = self.state_new.get_by_id_mut(account_id).unwrap().0; + let old_balance = account.info.balance; + account.info.balance = account.info.balance.saturating_add(balance); + + // march account as touched. + if !account.is_touched() { + account.mark_touch(); + self.journal.push(ENTRY::account_touched(account_id)); + } + + // add journal entry for balance increment. + self.journal + .push(ENTRY::balance_changed(account_id, old_balance)) + } + /// Increments the nonce of the account. #[inline] pub fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId) { diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index 18dc4c15d3..6dfd11ba00 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -37,16 +37,16 @@ pub fn reimburse_caller( ) -> Result<(), ::Error> { let basefee = context.block().basefee() as u128; // TODO save AccountId somewhere so we can access it here. - let caller = context.journal().caller_address_id().unwrap(); + let caller = context.journal().caller_address_id().unwrap().id(); let effective_gas_price = context.tx().effective_gas_price(basefee); // Return balance of not spend gas. - context.journal_mut().balance_incr( - caller.to_id(), + context.journal_mut().balance_incr_by_id( + caller, U256::from( effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128), ) + additional_refund, - )?; + ); Ok(()) } From ad0eeadae9124ded16ce56d5bda9c85f267cdc0c Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 11:54:15 +0200 Subject: [PATCH 15/37] sstore bench, lower capacity --- bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv | 3 ++- crates/context/src/journal/inner.rs | 3 +++ crates/handler/src/post_execution.rs | 1 - crates/state/src/types.rs | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv b/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv index 29eb985378..cd8a60acbe 100644 --- a/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv +++ b/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv @@ -136,4 +136,5 @@ SWAP13_50,SWAP13,50,600360036003600360036003600360036003600360036003600360036003 SWAP14_50,SWAP14,50,6003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d SWAP15_50,SWAP15,50,6003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e SWAP16_50,SWAP16,50,60036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f -CLZ_50,CLZ,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360031e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e5050505050505050505050 \ No newline at end of file +CLZ_50,CLZ,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360031e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e5050505050505050505050 +SSTORE_50, SSTORE,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360035555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 1039b84f77..b5d1a0bc66 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -311,6 +311,9 @@ impl JournalInner { Ok(address) } + /// Increments the balance of the account. + /// + /// Mark account as touched. #[inline] pub fn balance_incr_by_id(&mut self, account_id: AccountId, balance: U256) { let account = self.state_new.get_by_id_mut(account_id).unwrap().0; diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index 6dfd11ba00..ee58253ad9 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -1,5 +1,4 @@ use crate::FrameResult; -use context::journal; use context_interface::{ journaled_state::JournalTr, result::{ExecutionResult, HaltReasonTr}, diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 7c9a4aecee..ecd3cb93db 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -25,7 +25,7 @@ impl EvmState { pub fn new() -> Self { Self { index: HashMap::default(), - accounts: Vec::with_capacity(1024), + accounts: Vec::with_capacity(4), } } From abbbf3c5a6d0b4fdef5b3b4a3ac0263c0213f131 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 12:09:38 +0200 Subject: [PATCH 16/37] sload bench --- bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv | 5 +++-- crates/state/src/types.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv b/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv index cd8a60acbe..d6a0d9cdf3 100644 --- a/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv +++ b/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv @@ -136,5 +136,6 @@ SWAP13_50,SWAP13,50,600360036003600360036003600360036003600360036003600360036003 SWAP14_50,SWAP14,50,6003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d SWAP15_50,SWAP15,50,6003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e SWAP16_50,SWAP16,50,60036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f -CLZ_50,CLZ,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360031e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e5050505050505050505050 -SSTORE_50, SSTORE,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360035555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 +CLZ_50,CLZ,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360031e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e505050505050505050505000 +SSTORE_50, SSTORE,50,600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555500 +SLOAD_50, SLOAD,50,600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545400 \ No newline at end of file diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index ecd3cb93db..681a6fa686 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -25,7 +25,7 @@ impl EvmState { pub fn new() -> Self { Self { index: HashMap::default(), - accounts: Vec::with_capacity(4), + accounts: Vec::with_capacity(10), } } From 5fb09e64d11f6fb022d2ef91512be2a5aa848bee Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 12:31:20 +0200 Subject: [PATCH 17/37] default vec alloc --- crates/state/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 681a6fa686..7ea8d2af1a 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -25,7 +25,7 @@ impl EvmState { pub fn new() -> Self { Self { index: HashMap::default(), - accounts: Vec::with_capacity(10), + accounts: Vec::default(), } } From 063437521d05d59180e9a9e922a9dc760d1bbb5a Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 12:48:53 +0200 Subject: [PATCH 18/37] try reserve --- crates/state/src/types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 7ea8d2af1a..90851bc98f 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -20,6 +20,7 @@ pub struct EvmState { pub accounts: Vec<(Account, Address)>, } + impl EvmState { /// Create a new empty state. pub fn new() -> Self { @@ -148,6 +149,7 @@ impl EvmState { let account = fetch(address)?; let id = self.accounts.len(); entry.insert(id); + self.accounts.reserve(32); self.accounts.push((account, address)); let address_and_id = AddressAndId::new(address, id); Ok((&mut self.accounts.last_mut().unwrap().0, address_and_id)) From ad765bfe77d7ff50234a7666ab0820f4a4cd9c48 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 13:42:07 +0200 Subject: [PATCH 19/37] account state in pages --- crates/context/src/journal/inner.rs | 6 +- crates/database/src/in_memory_db.rs | 2 +- crates/database/src/states/cache.rs | 2 +- crates/ee-tests/src/op_revm_tests.rs | 8 +-- crates/handler/src/mainnet_builder.rs | 2 +- crates/handler/src/system_call.rs | 2 +- crates/inspector/src/gas.rs | 2 +- crates/primitives/src/address.rs | 2 +- crates/state/src/types.rs | 94 ++++++++++++++++++--------- 9 files changed, 77 insertions(+), 43 deletions(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index b5d1a0bc66..4bfcd7e01f 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -227,9 +227,9 @@ impl JournalInner { /// /// Panics if the account has not been loaded and is missing from the state set. #[inline] - pub fn account(&self, address_or_id: &AddressOrId) -> (&Account, AddressAndId) { + pub fn account(&self, address_or_id: AddressOrId) -> (&Account, AddressAndId) { self.state_new - .get(&address_or_id) + .get(address_or_id) .expect("Account expected to be loaded") // Always assume that acc is already loaded. } @@ -406,7 +406,7 @@ impl JournalInner { let checkpoint = self.checkpoint(); // Fetch balance of caller. - let (caller_acc, caller) = self.state_new.get(&caller_or_id).unwrap(); + let (caller_acc, caller) = self.state_new.get(caller_or_id).unwrap(); let caller_balance = caller_acc.info.balance; // Check if caller has enough balance to send to the created contract. if caller_balance < balance { diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index 89747e6232..fe5719f74d 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -192,7 +192,7 @@ impl CacheDB { impl DatabaseCommit for CacheDB { fn commit(&mut self, changes: EvmState) { - for (mut account, address) in changes.accounts { + for (mut account, address) in changes.accounts.into_iter().flatten() { if !account.is_touched() { continue; } diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index b40e257a1f..6e9d74465e 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -91,7 +91,7 @@ impl CacheState { /// Applies output of revm execution and create account transitions that are used to build BundleState. pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> { let mut transitions = Vec::with_capacity(evm_state.len()); - for (account, address) in evm_state.accounts.into_iter() { + for (account, address) in evm_state.accounts.into_iter().flatten() { if let Some(transition) = self.apply_account_state(address, account) { transitions.push((address, transition)); } diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index b8545d65bf..6bad66cd56 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -62,7 +62,7 @@ fn test_deposit_tx() { assert_eq!( output .state - .get(&AddressOrId::Address(Address::default())) + .get(AddressOrId::Address(Address::default())) .map(|a| a.0.info.balance), Some(U256::from(100)) ); @@ -105,7 +105,7 @@ fn test_halted_deposit_tx() { assert_eq!( output .state - .get(&BENCH_CALLER.into()) + .get(BENCH_CALLER.into()) .map(|a| a.0.info.balance), Some(U256::from(100) + BENCH_CALLER_BALANCE) ); @@ -1140,6 +1140,6 @@ fn test_system_call() { let _ = evm.system_call_one(BENCH_TARGET, bytes!("0x0001")); let state = evm.finalize(); - assert!(state.get(&SYSTEM_ADDRESS.into()).is_none()); - assert!(state.get(&BENCH_TARGET.into()).unwrap().0.is_touched()); + assert!(state.get(SYSTEM_ADDRESS.into()).is_none()); + assert!(state.get(BENCH_TARGET.into()).unwrap().0.is_touched()); } diff --git a/crates/handler/src/mainnet_builder.rs b/crates/handler/src/mainnet_builder.rs index bb9abc50fe..85a35b2a2f 100644 --- a/crates/handler/src/mainnet_builder.rs +++ b/crates/handler/src/mainnet_builder.rs @@ -119,7 +119,7 @@ mod test { .unwrap() .state; - let auth_acc = state.get(&signer.address().into()).unwrap(); + let auth_acc = state.get(signer.address().into()).unwrap(); assert_eq!(auth_acc.0.info.code, Some(Bytecode::new_eip7702(FFADDRESS))); assert_eq!(auth_acc.0.info.nonce, 1); assert_eq!( diff --git a/crates/handler/src/system_call.rs b/crates/handler/src/system_call.rs index f73a1f1b05..bcfeb72aeb 100644 --- a/crates/handler/src/system_call.rs +++ b/crates/handler/src/system_call.rs @@ -317,7 +317,7 @@ mod tests { assert_eq!( output .state - .get(&HISTORY_STORAGE_ADDRESS.into()) + .get(HISTORY_STORAGE_ADDRESS.into()) .unwrap() .0 .storage diff --git a/crates/inspector/src/gas.rs b/crates/inspector/src/gas.rs index 94ac777ca5..732679b0b6 100644 --- a/crates/inspector/src/gas.rs +++ b/crates/inspector/src/gas.rs @@ -222,7 +222,7 @@ mod tests { inspector.call_override.push(None); inspector.create_override.push(Some(CreateOutcome::new( InterpreterResult::new(InstructionResult::Revert, [0x02].into(), Gas::new(100_000)), - Some(AddressAndId::new(Address::ZERO, 0)), + Some(AddressAndId::new(Address::ZERO, (0, 0))), ))); let contract_data: Bytes = Bytes::from(vec![ diff --git a/crates/primitives/src/address.rs b/crates/primitives/src/address.rs index c421a50172..982406005e 100644 --- a/crates/primitives/src/address.rs +++ b/crates/primitives/src/address.rs @@ -2,7 +2,7 @@ use crate::Address; /// Address id. -pub type AccountId = usize; +pub type AccountId = (u32, u32); /// Address or account id. Id is used for internal account management. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 90851bc98f..bc309cf1b8 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -17,16 +17,16 @@ pub struct EvmState { pub index: HashMap, /// Accounts. /// TODO make pushing of new account smarter and introduce a Vec of Vec so we dont need to clone it. - pub accounts: Vec<(Account, Address)>, + pub accounts: Vec>, } - impl EvmState { /// Create a new empty state. pub fn new() -> Self { Self { index: HashMap::default(), - accounts: Vec::default(), + // Allocate first with 3 account (Caller, target, beneficiary) + accounts: vec![Vec::with_capacity(3)], } } @@ -39,15 +39,14 @@ impl EvmState { } /// Get an immutable reference to an account by address. - pub fn get(&self, address_or_id: &AddressOrId) -> Option<(&Account, AddressAndId)> { + pub fn get(&self, address_or_id: AddressOrId) -> Option<(&Account, AddressAndId)> { match address_or_id { - AddressOrId::Id(id) => self - .accounts - .get(*id) - .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))), - AddressOrId::Address(address) => self.index.get(address).and_then(|id| { + AddressOrId::Id(id) => self.get_by_id(id), + AddressOrId::Address(address) => self.index.get(&address).and_then(|id| { self.accounts - .get(*id) + .get(id.0 as usize) + .map(|accounts| accounts.get(id.1 as usize)) + .flatten() .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) }), } @@ -57,13 +56,12 @@ impl EvmState { #[inline] pub fn get_mut(&mut self, address_or_id: AddressOrId) -> Option<(&mut Account, AddressAndId)> { match address_or_id { - AddressOrId::Id(id) => self - .accounts - .get_mut(id) - .map(|(acc, address)| (acc, AddressAndId::new(*address, id))), + AddressOrId::Id(id) => self.get_by_id_mut(id), AddressOrId::Address(address) => self.index.get(&address).and_then(|id| { self.accounts - .get_mut(*id) + .get_mut(id.0 as usize) + .map(|accounts| accounts.get_mut(id.1 as usize)) + .flatten() .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) }), } @@ -73,16 +71,16 @@ impl EvmState { #[inline] pub fn get_by_id(&self, id: AccountId) -> Option<(&Account, AddressAndId)> { self.accounts - .get(id) + .get(id.0 as usize) + .map(|accounts| accounts.get(id.1 as usize)) + .flatten() .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) } /// Get a mutable reference to an account by id. #[inline] pub fn get_by_id_mut(&mut self, id: AccountId) -> Option<(&mut Account, AddressAndId)> { - self.accounts - .get_mut(id) - .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) + get_by_id_mut(&mut self.accounts, id) } /// Insert a new account or update an existing one. @@ -91,13 +89,14 @@ impl EvmState { match self.index.get(&address) { Some(&id) => { // Update existing account - self.accounts[id] = (account, address); + self.accounts[id.0 as usize][id.1 as usize] = (account, address); AddressAndId::new(address, id) } None => { - let id = self.accounts.len(); + // TODO Fix this + let id = (self.accounts.len() as u32, 0); self.index.insert(address, id); - self.accounts.push((account, address)); + self.accounts.push(vec![(account, address)]); AddressAndId::new(address, id) } } @@ -126,7 +125,7 @@ impl EvmState { /// Iterate over all accounts. pub fn iter(&self) -> impl Iterator + '_ { - self.accounts.iter() + self.accounts.iter().flat_map(|accounts| accounts.iter()) } /// Get a mutable reference to an account by address or fetch it if it doesn't exist. @@ -141,23 +140,58 @@ impl EvmState { { match self.index.entry(address) { Entry::Occupied(entry) => { - let address_and_id = AddressAndId::new(address, *entry.get()); - let (account, _) = self.accounts.get_mut(*entry.get()).unwrap(); - Ok((account, address_and_id)) + Ok(get_by_id_mut(&mut self.accounts, *entry.get()).expect("Account to be present")) } Entry::Vacant(entry) => { let account = fetch(address)?; - let id = self.accounts.len(); + let id = push_account(&mut self.accounts, account, address); entry.insert(id); - self.accounts.reserve(32); - self.accounts.push((account, address)); let address_and_id = AddressAndId::new(address, id); - Ok((&mut self.accounts.last_mut().unwrap().0, address_and_id)) + Ok(( + &mut self.accounts.last_mut().unwrap().last_mut().unwrap().0, + address_and_id, + )) } } } } +/// Push an account to the accounts vector, allocating a new page if last page is full. +/// +/// Returns the account id that was assigned to the account. +#[inline] +fn push_account( + accounts: &mut Vec>, + account: Account, + address: Address, +) -> AccountId { + let page_id = accounts.len() as u32; + if let Some(last) = accounts.last_mut() { + if last.len() < 100 { + let id = (page_id - 1, last.len() as u32); + last.push((account, address)); + return id; + } + } + let mut vec = Vec::with_capacity(100); + vec.push((account, address)); + accounts.push(vec); + (page_id, 0) +} + +/// Get a mutable reference to an account by id. +#[inline] +fn get_by_id_mut( + accounts: &mut Vec>, + id: AccountId, +) -> Option<(&mut Account, AddressAndId)> { + accounts + .get_mut(id.0 as usize) + .map(|accounts| accounts.get_mut(id.1 as usize)) + .flatten() + .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) +} + impl Default for EvmState { fn default() -> Self { Self::new() From 0e4861b82fbdf5741f7ff1d346d8be9bd94ec78e Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 14:03:05 +0200 Subject: [PATCH 20/37] remove some of checks for AccountId gets --- .../context/interface/src/journaled_state.rs | 4 +- crates/context/src/journal.rs | 8 +-- crates/context/src/journal/inner.rs | 10 ++-- crates/handler/src/frame.rs | 8 +-- crates/state/src/types.rs | 53 ++++++++++--------- 5 files changed, 41 insertions(+), 42 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index d9b92d5303..684ea137a0 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -130,10 +130,10 @@ pub trait JournalTr { ) -> Result, ::Error>; /// Returns the account by id. - fn get_account_mut(&mut self, account_id: AccountId) -> Option<&mut Account>; + fn get_account_mut(&mut self, account_id: AccountId) -> &mut Account; /// Fast fetch the account by id. - fn get_account(&mut self, account_id: AccountId) -> Option<&Account>; + fn get_account(&mut self, account_id: AccountId) -> &Account; /// Sets the caller id. fn set_caller_address_id(&mut self, id: AddressAndId); diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 74e4d306b2..115152fb48 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -183,13 +183,13 @@ impl JournalTr for Journal { } #[inline] - fn get_account_mut(&mut self, account_id: AccountId) -> Option<&mut Account> { - self.inner.state().get_by_id_mut(account_id).map(|(a, _)| a) + fn get_account_mut(&mut self, account_id: AccountId) -> &mut Account { + self.inner.state().get_by_id_mut(account_id).0 } #[inline] - fn get_account(&mut self, account_id: AccountId) -> Option<&Account> { - self.inner.state().get_by_id(account_id).map(|(a, _)| a) + fn get_account(&mut self, account_id: AccountId) -> &Account { + self.inner.state().get_by_id(account_id).0 } /// Returns call depth. diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 4bfcd7e01f..9af7c8357d 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -316,7 +316,7 @@ impl JournalInner { /// Mark account as touched. #[inline] pub fn balance_incr_by_id(&mut self, account_id: AccountId, balance: U256) { - let account = self.state_new.get_by_id_mut(account_id).unwrap().0; + let account = self.state_new.get_by_id_mut(account_id).0; let old_balance = account.info.balance; account.info.balance = account.info.balance.saturating_add(balance); @@ -348,13 +348,13 @@ impl JournalInner { balance: U256, ) -> Option { if balance.is_zero() { - let to_account = self.state_new.get_by_id_mut(to).unwrap().0; + let to_account = self.state_new.get_by_id_mut(to).0; Self::touch_account(&mut self.journal, to, to_account); return None; } // sub balance from - let (from_account, _) = self.state_new.get_by_id_mut(from).unwrap(); + let (from_account, _) = self.state_new.get_by_id_mut(from); Self::touch_account(&mut self.journal, from, from_account); let from_balance = &mut from_account.info.balance; @@ -364,7 +364,7 @@ impl JournalInner { *from_balance = from_balance_decr; // add balance to - let (to_account, _) = self.state_new.get_by_id_mut(to).unwrap(); + let (to_account, _) = self.state_new.get_by_id_mut(to); Self::touch_account(&mut self.journal, to, to_account); let to_balance = &mut to_account.info.balance; let Some(to_balance_incr) = to_balance.checked_add(balance) else { @@ -669,7 +669,7 @@ impl JournalInner { }) }, )?, - AddressOrId::Id(id) => self.state_new.get_by_id_mut(id).unwrap(), + AddressOrId::Id(id) => self.state_new.get_by_id_mut(id), }; let mut is_cold = account.mark_warm_with_transaction_id(self.transaction_id); diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 4933a7f1e2..68ce9090dd 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -222,13 +222,9 @@ impl EthFrame { // let mut bytecode = account.0.info.code.clone().unwrap_or_default(); let account = if let Some(delegated_acc) = acc_load.delegated_account_address { - ctx.journal_mut() - .get_account(delegated_acc.id()) - .expect("delegated account should be loaded") + ctx.journal_mut().get_account(delegated_acc.id()) } else { - ctx.journal_mut() - .get_account(acc_load.address_and_id.id()) - .expect("account should be loaded") + ctx.journal_mut().get_account(acc_load.address_and_id.id()) }; let code_hash = account.info.code_hash(); diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index bc309cf1b8..608d070ca3 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -41,14 +41,11 @@ impl EvmState { /// Get an immutable reference to an account by address. pub fn get(&self, address_or_id: AddressOrId) -> Option<(&Account, AddressAndId)> { match address_or_id { - AddressOrId::Id(id) => self.get_by_id(id), - AddressOrId::Address(address) => self.index.get(&address).and_then(|id| { - self.accounts - .get(id.0 as usize) - .map(|accounts| accounts.get(id.1 as usize)) - .flatten() - .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) - }), + AddressOrId::Id(id) => Some(self.get_by_id(id)), + AddressOrId::Address(address) => self + .index + .get(&address) + .map(|id| get_by_id(&self.accounts, *id)), } } @@ -56,7 +53,7 @@ impl EvmState { #[inline] pub fn get_mut(&mut self, address_or_id: AddressOrId) -> Option<(&mut Account, AddressAndId)> { match address_or_id { - AddressOrId::Id(id) => self.get_by_id_mut(id), + AddressOrId::Id(id) => Some(self.get_by_id_mut(id)), AddressOrId::Address(address) => self.index.get(&address).and_then(|id| { self.accounts .get_mut(id.0 as usize) @@ -69,17 +66,13 @@ impl EvmState { /// Get an immutable reference to an account by id. #[inline] - pub fn get_by_id(&self, id: AccountId) -> Option<(&Account, AddressAndId)> { - self.accounts - .get(id.0 as usize) - .map(|accounts| accounts.get(id.1 as usize)) - .flatten() - .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) + pub fn get_by_id(&self, id: AccountId) -> (&Account, AddressAndId) { + get_by_id(&self.accounts, id) } /// Get a mutable reference to an account by id. #[inline] - pub fn get_by_id_mut(&mut self, id: AccountId) -> Option<(&mut Account, AddressAndId)> { + pub fn get_by_id_mut(&mut self, id: AccountId) -> (&mut Account, AddressAndId) { get_by_id_mut(&mut self.accounts, id) } @@ -139,9 +132,7 @@ impl EvmState { F: FnOnce(Address) -> Result, { match self.index.entry(address) { - Entry::Occupied(entry) => { - Ok(get_by_id_mut(&mut self.accounts, *entry.get()).expect("Account to be present")) - } + Entry::Occupied(entry) => Ok(get_by_id_mut(&mut self.accounts, *entry.get())), Entry::Vacant(entry) => { let account = fetch(address)?; let id = push_account(&mut self.accounts, account, address); @@ -184,12 +175,24 @@ fn push_account( fn get_by_id_mut( accounts: &mut Vec>, id: AccountId, -) -> Option<(&mut Account, AddressAndId)> { - accounts - .get_mut(id.0 as usize) - .map(|accounts| accounts.get_mut(id.1 as usize)) - .flatten() - .map(|(acc, address)| (acc, AddressAndId::new(*address, id))) +) -> (&mut Account, AddressAndId) { + let account = unsafe { + accounts + .get_unchecked_mut(id.0 as usize) + .get_unchecked_mut(id.1 as usize) + }; + (&mut account.0, AddressAndId::new(account.1, id)) +} + +/// Get an immutable reference to an account by id. +#[inline] +fn get_by_id(accounts: &Vec>, id: AccountId) -> (&Account, AddressAndId) { + let account = unsafe { + accounts + .get_unchecked(id.0 as usize) + .get_unchecked(id.1 as usize) + }; + (&account.0, AddressAndId::new(account.1, id)) } impl Default for EvmState { From 93e7e61025fbbb163761b9eb68c2d313d696d413 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 15:06:37 +0200 Subject: [PATCH 21/37] add load caller/to/beneficiary at one place --- .../context/interface/src/journaled_state.rs | 13 ++-- crates/context/src/journal.rs | 23 ++++--- crates/context/src/journal/warm_addresses.rs | 18 ++--- crates/database/interface/src/either.rs | 4 +- crates/database/interface/src/lib.rs | 4 +- crates/database/interface/src/try_commit.rs | 3 +- crates/handler/src/frame.rs | 2 +- crates/handler/src/handler.rs | 2 +- crates/handler/src/post_execution.rs | 9 ++- crates/handler/src/pre_execution.rs | 22 ++++--- crates/inspector/src/handler.rs | 66 +++++++++++-------- 11 files changed, 93 insertions(+), 73 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 684ea137a0..3d416204e9 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -75,9 +75,6 @@ pub trait JournalTr { self.warm_account_and_storage(address, []) } - /// Warms the coinbase account. - fn warm_coinbase_account(&mut self, address: Address); - /// Warms the precompiles. Precompile account will not be fetched from database /// /// Warming of precompiles assumes that account are frequently accessed and it will @@ -130,14 +127,20 @@ pub trait JournalTr { ) -> Result, ::Error>; /// Returns the account by id. - fn get_account_mut(&mut self, account_id: AccountId) -> &mut Account; + fn get_account_mut(&mut self, account_id: AccountId) -> (&mut Account, AddressAndId); /// Fast fetch the account by id. - fn get_account(&mut self, account_id: AccountId) -> &Account; + fn get_account(&mut self, account_id: AccountId) -> (&Account, AddressAndId); /// Sets the caller id. fn set_caller_address_id(&mut self, id: AddressAndId); + /// Sets the coinbase id. + fn set_coinbase_address_id(&mut self, id: AddressAndId); + + /// Returns the coinbase address and id. + fn coinbase_address_id(&self) -> Option; + /// Returns the caller address and id. fn caller_address_id(&self) -> Option; diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 115152fb48..3506d3d3c0 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -146,11 +146,6 @@ impl JournalTr for Journal { .selfdestruct(&mut self.database, address_or_id, target) } - #[inline] - fn warm_coinbase_account(&mut self, address: Address) { - self.inner.warm_addresses.set_coinbase(address); - } - #[inline] fn set_caller_address_id(&mut self, id: AddressAndId) { self.inner.warm_addresses.set_caller(id); @@ -161,6 +156,16 @@ impl JournalTr for Journal { self.inner.warm_addresses.set_tx_target(id); } + #[inline] + fn set_coinbase_address_id(&mut self, id: AddressAndId) { + self.inner.warm_addresses.set_coinbase(id); + } + + #[inline] + fn coinbase_address_id(&self) -> Option { + self.inner.warm_addresses.coinbase() + } + #[inline] fn caller_address_id(&self) -> Option { self.inner.warm_addresses.caller() @@ -183,13 +188,13 @@ impl JournalTr for Journal { } #[inline] - fn get_account_mut(&mut self, account_id: AccountId) -> &mut Account { - self.inner.state().get_by_id_mut(account_id).0 + fn get_account_mut(&mut self, account_id: AccountId) -> (&mut Account, AddressAndId) { + self.inner.state().get_by_id_mut(account_id) } #[inline] - fn get_account(&mut self, account_id: AccountId) -> &Account { - self.inner.state().get_by_id(account_id).0 + fn get_account(&mut self, account_id: AccountId) -> (&Account, AddressAndId) { + self.inner.state().get_by_id(account_id) } /// Returns call depth. diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs index e84c6416bc..58ae28a763 100644 --- a/crates/context/src/journal/warm_addresses.rs +++ b/crates/context/src/journal/warm_addresses.rs @@ -17,7 +17,7 @@ pub struct WarmAddresses { /// `true` if all precompiles are short addresses. all_short_addresses: bool, /// Coinbase address. - coinbase: Option
, + coinbase: Option, /// Caller address and id. caller: Option, /// Tx target address and id. @@ -52,7 +52,7 @@ impl WarmAddresses { /// Returns the coinbase address. #[inline] - pub fn coinbase(&self) -> Option
{ + pub fn coinbase(&self) -> Option { self.coinbase } @@ -89,7 +89,7 @@ impl WarmAddresses { /// Set the coinbase address. #[inline] - pub fn set_coinbase(&mut self, address: Address) { + pub fn set_coinbase(&mut self, address: AddressAndId) { self.coinbase = Some(address); } @@ -117,9 +117,9 @@ impl WarmAddresses { #[inline] pub fn is_warm(&self, address: &Address) -> bool { // check if it is coinbase - if Some(*address) == self.coinbase { - return true; - } + // if Some(*address) == self.coinbase { + // return true; + // } // if there are no precompiles, it is cold loaded and bitvec is not set. if self.precompile_set.is_empty() { @@ -170,9 +170,9 @@ mod tests { let coinbase_addr = address!("1234567890123456789012345678901234567890"); // Test setting coinbase - warm_addresses.set_coinbase(coinbase_addr); - assert_eq!(warm_addresses.coinbase, Some(coinbase_addr)); - assert!(warm_addresses.is_warm(&coinbase_addr)); + //warm_addresses.set_coinbase(coinbase_addr); + //assert_eq!(warm_addresses.coinbase, Some(coinbase_addr)); + //assert!(warm_addresses.is_warm(&coinbase_addr)); // Test clearing coinbase warm_addresses.clear_addresses(); diff --git a/crates/database/interface/src/either.rs b/crates/database/interface/src/either.rs index a78b730a47..0c191fe548 100644 --- a/crates/database/interface/src/either.rs +++ b/crates/database/interface/src/either.rs @@ -2,8 +2,8 @@ use crate::{Database, DatabaseCommit, DatabaseRef}; use either::Either; -use primitives::{Address, HashMap, StorageKey, StorageValue, B256}; -use state::{Account, AccountInfo, Bytecode, EvmState}; +use primitives::{Address, StorageKey, StorageValue, B256}; +use state::{AccountInfo, Bytecode, EvmState}; impl Database for Either where diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index b3ca6f92ae..c797e0da23 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -9,8 +9,8 @@ use core::convert::Infallible; use auto_impl::auto_impl; use core::error::Error; -use primitives::{address, Address, HashMap, StorageKey, StorageValue, B256, U256}; -use state::{Account, AccountInfo, Bytecode, EvmState}; +use primitives::{address, Address, StorageKey, StorageValue, B256, U256}; +use state::{AccountInfo, Bytecode, EvmState}; use std::string::String; /// Address with all `0xff..ff` in it. Used for testing. diff --git a/crates/database/interface/src/try_commit.rs b/crates/database/interface/src/try_commit.rs index 435d4c82a8..cda261f90b 100644 --- a/crates/database/interface/src/try_commit.rs +++ b/crates/database/interface/src/try_commit.rs @@ -1,8 +1,7 @@ //! Try database commit interface. use crate::DatabaseCommit; use core::{convert::Infallible, error::Error, fmt}; -use primitives::{Address, HashMap}; -use state::{Account, EvmState}; +use state::EvmState; use std::sync::Arc; /// EVM database commit interface that can fail. diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 68ce9090dd..2426c8dad5 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -221,7 +221,7 @@ impl EthFrame { // let mut bytecode = account.0.info.code.clone().unwrap_or_default(); - let account = if let Some(delegated_acc) = acc_load.delegated_account_address { + let (account, _) = if let Some(delegated_acc) = acc_load.delegated_account_address { ctx.journal_mut().get_account(delegated_acc.id()) } else { ctx.journal_mut().get_account(acc_load.address_and_id.id()) diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 345af9a958..ee520bb5b5 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -174,8 +174,8 @@ pub trait Handler { /// Returns the gas refund amount from EIP-7702. Authorizations are applied before execution begins. #[inline] fn pre_execution(&self, evm: &mut Self::Evm) -> Result { - self.validate_against_state_and_deduct_caller(evm)?; self.load_accounts(evm)?; + self.validate_against_state_and_deduct_caller(evm)?; let gas = self.apply_eip7702_auth_list(evm)?; Ok(gas) diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index ee58253ad9..e42c1e35fe 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -56,8 +56,7 @@ pub fn reward_beneficiary( context: &mut CTX, gas: &Gas, ) -> Result<(), ::Error> { - // TODO save beneficiary AccountId somewhere so we can access it here. - let beneficiary = context.block().beneficiary().into(); + let beneficiary = context.journal().coinbase_address_id().unwrap(); let basefee = context.block().basefee() as u128; let effective_gas_price = context.tx().effective_gas_price(basefee); @@ -70,10 +69,10 @@ pub fn reward_beneficiary( }; // reward beneficiary - context.journal_mut().balance_incr( - beneficiary, + context.journal_mut().balance_incr_by_id( + beneficiary.id(), U256::from(coinbase_gas_price * gas.used() as u128), - )?; + ); Ok(()) } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index c9085dcbf0..2b75a0236f 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -25,6 +25,7 @@ pub fn load_accounts< >( evm: &mut EVM, ) -> Result<(), ERROR> { + let beneficiary = evm.ctx().block().beneficiary().into(); let (context, precompiles) = evm.ctx_precompiles(); let gen_spec = context.cfg().spec(); @@ -42,13 +43,6 @@ pub fn load_accounts< .warm_precompiles(precompiles.warm_addresses().collect()); } - // Load coinbase - // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm - if spec.is_enabled_in(SpecId::SHANGHAI) { - let coinbase = context.block().beneficiary(); - context.journal_mut().warm_coinbase_account(coinbase); - } - // Load access list let (tx, journal) = context.tx_journal_mut(); // legacy is only tx type that does not have access list. @@ -63,12 +57,23 @@ pub fn load_accounts< } } + let (_, id) = journal.load_account_code(tx.caller().into())?.data; + journal.set_caller_address_id(id); + // load tx target and set its id in journal. if let TxKind::Call(target) = tx.kind() { let (_, id) = journal.load_account_code(target.into())?.data; journal.set_tx_target_address_id(id); } + let (coinbase, id) = journal.load_account_code(beneficiary)?.data; + // Load coinbase + // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm + if spec.is_enabled_in(SpecId::SHANGHAI) { + coinbase.mark_touch(); + } + journal.set_coinbase_address_id(id); + Ok(()) } @@ -125,12 +130,13 @@ pub fn validate_against_state_and_deduct_caller< let is_balance_check_disabled = context.cfg().is_balance_check_disabled(); let is_eip3607_disabled = context.cfg().is_eip3607_disabled(); let is_nonce_check_disabled = context.cfg().is_nonce_check_disabled(); + let caller = context.journal_mut().caller_address_id().unwrap(); let (tx, journal) = context.tx_journal_mut(); // Load caller's account. // TODO load account, obtains AccountId and store it somewhere so we can access later. - let (caller_account, caller) = journal.load_account_code(tx.caller().into())?.data; + let (caller_account, _) = journal.get_account_mut(caller.id()); validate_account_nonce_and_code( &mut caller_account.info, diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index 2af177c7bf..6920f33b6c 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -1,5 +1,5 @@ use crate::{Inspector, InspectorEvmTr, JournalExt}; -use context::{result::ExecutionResult, ContextTr, JournalEntry, Transaction}; +use context::{result::ExecutionResult, ContextTr, JournalEntry, JournalTr, Transaction}; use handler::{evm::FrameTr, EvmTr, FrameResult, Handler, ItemOrResult}; use interpreter::{ instructions::InstructionTable, @@ -231,9 +231,9 @@ where // Handle selfdestruct. if let InterpreterAction::Return(result) = &next_action { - // if result.result == InstructionResult::SelfDestruct { - // inspect_selfdestruct(context, &mut inspector); - // } + if result.result == InstructionResult::SelfDestruct { + inspect_selfdestruct(context, &mut inspector); + } } next_action @@ -263,28 +263,36 @@ fn inspect_log( inspector.log(interpreter, context, log); } -// #[inline(never)] -// #[cold] -// fn inspect_selfdestruct(context: &mut CTX, inspector: &mut impl Inspector) -// where -// CTX: ContextTr + Host, -// IT: InterpreterTypes, -// { -// if let Some( -// JournalEntry::AccountDestroyed { -// account_id: 0, -// target: to, -// had_balance: balance, -// .. -// } -// | JournalEntry::BalanceTransfer { -// from: contract, -// to, -// balance, -// .. -// }, -// ) = context.journal_mut().journal().last() -// { -// inspector.selfdestruct(*contract, *to, *balance); -// } -// } +#[inline(never)] +#[cold] +fn inspect_selfdestruct(context: &mut CTX, inspector: &mut impl Inspector) +where + CTX: ContextTr + Host, + IT: InterpreterTypes, +{ + let journal = context.journal_mut(); + let journal = journal.journal(); + let Some( + JournalEntry::AccountDestroyed { + account_id: contract, + target: to, + had_balance: balance, + .. + } + | JournalEntry::BalanceTransfer { + from: contract, + to, + balance, + .. + }, + ) = journal.last() + else { + return; + }; + let contract = *contract; + let to = *to; + let balance = *balance; + let contract = *context.journal_mut().get_account(contract).1.address(); + let to = *context.journal_mut().get_account(to).1.address(); + inspector.selfdestruct(contract, to, balance); +} From 279491d434e10b4b4b28dd3aa436d02d6a8b84d7 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 22:22:32 +0200 Subject: [PATCH 22/37] rename state_new to state --- bins/revme/src/cmd/bench/transfer_multi.rs | 2 +- crates/context/src/journal/inner.rs | 59 ++++++++++--------- crates/database/src/in_memory_db.rs | 2 +- crates/ee-tests/src/revm_tests.rs | 12 ++-- crates/handler/src/handler.rs | 6 +- crates/handler/src/pre_execution.rs | 3 - crates/inspector/src/inspector.rs | 4 +- .../src/interpreter_action/create_outcome.rs | 2 +- 8 files changed, 46 insertions(+), 44 deletions(-) diff --git a/bins/revme/src/cmd/bench/transfer_multi.rs b/bins/revme/src/cmd/bench/transfer_multi.rs index d22c467677..6c07c8cc98 100644 --- a/bins/revme/src/cmd/bench/transfer_multi.rs +++ b/bins/revme/src/cmd/bench/transfer_multi.rs @@ -41,7 +41,7 @@ pub fn run(criterion: &mut Criterion) { .caller(BENCH_CALLER) .kind(TxKind::Call((target + U256::from(i)).into_address())) .value(U256::from(1)) - .gas_price(0) + .gas_price(1) .gas_priority_fee(None) .gas_limit(30_000) .build() diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 9af7c8357d..b5c719240d 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -24,7 +24,7 @@ use std::vec::Vec; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct JournalInner { /// The current state new - pub state_new: EvmState, + pub state: EvmState, /// Transient storage that is discarded after every transaction. /// /// See [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153). @@ -71,7 +71,7 @@ impl JournalInner { /// In ordinary case this is precompile or beneficiary. pub fn new() -> JournalInner { Self { - state_new: EvmState::new(), + state: EvmState::new(), transient_storage: TransientStorage::default(), logs: Vec::new(), journal: Vec::default(), @@ -99,7 +99,7 @@ impl JournalInner { // Clears all field from JournalInner. Doing it this way to avoid // missing any field. let Self { - state_new, + state, transient_storage, logs, depth, @@ -110,6 +110,7 @@ impl JournalInner { } = self; // Spec precompiles and state are not changed. It is always set again execution. let _ = spec; + let _ = state; transient_storage.clear(); *depth = 0; @@ -128,7 +129,7 @@ impl JournalInner { pub fn discard_tx(&mut self) { // if there is no journal entries, there has not been any changes. let Self { - state_new, + state, transient_storage, logs, depth, @@ -140,7 +141,7 @@ impl JournalInner { let is_spurious_dragon_enabled = spec.is_enabled_in(SPURIOUS_DRAGON); // iterate over all journals entries and revert our global state journal.drain(..).rev().for_each(|entry| { - entry.revert(state_new, None, is_spurious_dragon_enabled); + entry.revert(state, None, is_spurious_dragon_enabled); }); transient_storage.clear(); *depth = 0; @@ -160,7 +161,7 @@ impl JournalInner { // Clears all field from JournalInner. Doing it this way to avoid // missing any field. let Self { - state_new, + state, transient_storage, logs, depth, @@ -174,7 +175,7 @@ impl JournalInner { // Clear coinbase address warming for next tx warm_addresses.clear_addresses(); - let state = mem::take(state_new); + let state = mem::take(state); logs.clear(); transient_storage.clear(); @@ -191,7 +192,7 @@ impl JournalInner { /// Return reference to state. #[inline] pub fn state(&mut self) -> &mut EvmState { - &mut self.state_new + &mut self.state } /// Sets SpecId. @@ -205,7 +206,7 @@ impl JournalInner { /// be removed from state. #[inline] pub fn touch(&mut self, address_or_id: AddressOrId) { - if let Some((account, id)) = self.state_new.get_mut(address_or_id) { + if let Some((account, id)) = self.state.get_mut(address_or_id) { Self::touch_account(&mut self.journal, id.id(), account); } } @@ -228,7 +229,7 @@ impl JournalInner { /// Panics if the account has not been loaded and is missing from the state set. #[inline] pub fn account(&self, address_or_id: AddressOrId) -> (&Account, AddressAndId) { - self.state_new + self.state .get(address_or_id) .expect("Account expected to be loaded") // Always assume that acc is already loaded. } @@ -238,7 +239,7 @@ impl JournalInner { /// Note: Assume account is warm and that hash is calculated from code. #[inline] pub fn set_code_with_hash(&mut self, address_or_id: AddressOrId, code: Bytecode, hash: B256) { - let (account, address) = self.state_new.get_mut(address_or_id).unwrap(); + let (account, address) = self.state.get_mut(address_or_id).unwrap(); Self::touch_account(&mut self.journal, address.id(), account); self.journal.push(ENTRY::code_changed(address.id())); @@ -273,7 +274,7 @@ impl JournalInner { old_balance: U256, bump_nonce: bool, ) { - let id = self.state_new.get_id(&address_or_id).unwrap(); + let id = self.state.get_id(&address_or_id).unwrap(); // account balance changed. self.journal.push(ENTRY::balance_changed(id, old_balance)); // account is touched. @@ -316,7 +317,7 @@ impl JournalInner { /// Mark account as touched. #[inline] pub fn balance_incr_by_id(&mut self, account_id: AccountId, balance: U256) { - let account = self.state_new.get_by_id_mut(account_id).0; + let account = self.state.get_by_id_mut(account_id).0; let old_balance = account.info.balance; account.info.balance = account.info.balance.saturating_add(balance); @@ -335,7 +336,7 @@ impl JournalInner { #[inline] pub fn nonce_bump_journal_entry(&mut self, address_or_id: AddressOrId) { // TODO check if it is okay to unwrap here - let id = self.state_new.get_id(&address_or_id).unwrap(); + let id = self.state.get_id(&address_or_id).unwrap(); self.journal.push(ENTRY::nonce_changed(id)); } @@ -348,13 +349,13 @@ impl JournalInner { balance: U256, ) -> Option { if balance.is_zero() { - let to_account = self.state_new.get_by_id_mut(to).0; + let to_account = self.state.get_by_id_mut(to).0; Self::touch_account(&mut self.journal, to, to_account); return None; } // sub balance from - let (from_account, _) = self.state_new.get_by_id_mut(from); + let (from_account, _) = self.state.get_by_id_mut(from); Self::touch_account(&mut self.journal, from, from_account); let from_balance = &mut from_account.info.balance; @@ -364,7 +365,7 @@ impl JournalInner { *from_balance = from_balance_decr; // add balance to - let (to_account, _) = self.state_new.get_by_id_mut(to); + let (to_account, _) = self.state.get_by_id_mut(to); Self::touch_account(&mut self.journal, to, to_account); let to_balance = &mut to_account.info.balance; let Some(to_balance_incr) = to_balance.checked_add(balance) else { @@ -406,7 +407,7 @@ impl JournalInner { let checkpoint = self.checkpoint(); // Fetch balance of caller. - let (caller_acc, caller) = self.state_new.get(caller_or_id).unwrap(); + let (caller_acc, caller) = self.state.get(caller_or_id).unwrap(); let caller_balance = caller_acc.info.balance; // Check if caller has enough balance to send to the created contract. if caller_balance < balance { @@ -415,7 +416,7 @@ impl JournalInner { } // Newly created account is present, as we just loaded it. - let (target_acc, target) = self.state_new.get_mut(target_or_id).unwrap(); + let (target_acc, target) = self.state.get_mut(target_or_id).unwrap(); let last_journal = &mut self.journal; // New account can be created if: @@ -451,7 +452,7 @@ impl JournalInner { target_acc.info.balance = new_balance; // safe to decrement for the caller as balance check is already done. - self.state_new + self.state .get_mut(AddressOrId::Id(caller.id())) .unwrap() .0 @@ -485,7 +486,7 @@ impl JournalInner { #[inline] pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) { let is_spurious_dragon_enabled = self.spec.is_enabled_in(SPURIOUS_DRAGON); - let state = &mut self.state_new; + let state = &mut self.state; let transient_storage = &mut self.transient_storage; self.depth -= 1; self.logs.truncate(checkpoint.log_i); @@ -517,7 +518,7 @@ impl JournalInner { address_or_id: AddressOrId, target: Address, ) -> Result, DB::Error> { - let (acc, address) = self.state_new.get_mut(address_or_id).unwrap(); + let (acc, address) = self.state.get_mut(address_or_id).unwrap(); let balance = acc.info.balance; let spec = self.spec; @@ -536,7 +537,7 @@ impl JournalInner { } } - let (acc, _) = self.state_new.get_mut(address_or_id).unwrap(); + let (acc, _) = self.state.get_mut(address_or_id).unwrap(); let destroyed_status = if !acc.is_selfdestructed() { SelfdestructionRevertStatus::GloballySelfdestroyed @@ -657,7 +658,7 @@ impl JournalInner { storage_keys: impl IntoIterator, ) -> Result, DB::Error> { let (account, address_and_id) = match address_or_id { - AddressOrId::Address(address) => self.state_new.get_mut_or_fetch( + AddressOrId::Address(address) => self.state.get_mut_or_fetch( address, |address| -> Result { db.basic(address).map(|account| { @@ -669,7 +670,7 @@ impl JournalInner { }) }, )?, - AddressOrId::Id(id) => self.state_new.get_by_id_mut(id), + AddressOrId::Id(id) => self.state.get_by_id_mut(id), }; let mut is_cold = account.mark_warm_with_transaction_id(self.transaction_id); @@ -736,7 +737,7 @@ impl JournalInner { key: StorageKey, ) -> Result, DB::Error> { // assume acc is warm - let (account, id) = self.state_new.get_mut(address_or_id).unwrap(); + let (account, id) = self.state.get_mut(address_or_id).unwrap(); // only if account is created in this tx we can assume that storage is empty. sload_with_account(account, db, &mut self.journal, self.transaction_id, id, key) } @@ -756,7 +757,7 @@ impl JournalInner { ) -> Result, DB::Error> { // assume that acc exists and load the slot. let present = self.sload(db, address_or_id, key)?; - let (acc, id) = self.state_new.get_mut(address_or_id).unwrap(); + let (acc, id) = self.state.get_mut(address_or_id).unwrap(); // if there is no original value in dirty return present value, that is our original. let slot = acc.storage.get_mut(&key).unwrap(); @@ -792,7 +793,7 @@ impl JournalInner { /// EIP-1153: Transient storage opcodes #[inline] pub fn tload(&mut self, address_or_id: AddressOrId, key: StorageKey) -> StorageValue { - let id = self.state_new.get_id(&address_or_id).unwrap(); + let id = self.state.get_id(&address_or_id).unwrap(); self.transient_storage .get(&(id, key)) .copied() @@ -807,7 +808,7 @@ impl JournalInner { /// EIP-1153: Transient storage opcodes #[inline] pub fn tstore(&mut self, address_or_id: AddressOrId, key: StorageKey, new: StorageValue) { - let id = self.state_new.get_id(&address_or_id).unwrap(); + let id = self.state.get_id(&address_or_id).unwrap(); let had_value = if new.is_zero() { // if new values is zero, remove entry from transient storage. // if previous values was some insert it inside journal. diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index fe5719f74d..4f95b57358 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -6,7 +6,7 @@ use database_interface::{ use primitives::{ hash_map::Entry, Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; -use state::{Account, AccountInfo, Bytecode, EvmState}; +use state::{AccountInfo, Bytecode, EvmState}; use std::vec::Vec; /// A [Database] implementation that stores all state changes in memory. diff --git a/crates/ee-tests/src/revm_tests.rs b/crates/ee-tests/src/revm_tests.rs index 4672a86c63..b11ba7ad95 100644 --- a/crates/ee-tests/src/revm_tests.rs +++ b/crates/ee-tests/src/revm_tests.rs @@ -52,7 +52,7 @@ fn test_selfdestruct_multi_tx() { let (destroyed_acc, _) = evm .ctx .journal_mut() - .state_new + .state .get_mut(BENCH_TARGET.into()) .unwrap(); @@ -72,7 +72,7 @@ fn test_selfdestruct_multi_tx() { let (destroyed_acc, _) = evm .ctx .journal_mut() - .state_new + .state .get_mut(BENCH_TARGET.into()) .unwrap(); @@ -115,7 +115,7 @@ fn test_multi_tx_create() { let (created_acc, _) = evm .ctx .journal_mut() - .state_new + .state .get_mut(created_address.into()) .unwrap(); @@ -139,7 +139,7 @@ fn test_multi_tx_create() { let (created_acc, _) = evm .ctx .journal_mut() - .state_new + .state .get_mut(created_address.into()) .unwrap(); @@ -156,7 +156,7 @@ fn test_multi_tx_create() { // reset caller nonce evm.ctx .journal_mut() - .state_new + .state .get_mut(BENCH_CALLER.into()) .unwrap() .0 @@ -180,7 +180,7 @@ fn test_multi_tx_create() { let (created_acc, _) = evm .ctx .journal_mut() - .state_new + .state .get_mut(created_address.into()) .unwrap(); diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index ee520bb5b5..facedf58a6 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -174,8 +174,8 @@ pub trait Handler { /// Returns the gas refund amount from EIP-7702. Authorizations are applied before execution begins. #[inline] fn pre_execution(&self, evm: &mut Self::Evm) -> Result { - self.load_accounts(evm)?; self.validate_against_state_and_deduct_caller(evm)?; + self.load_accounts(evm)?; let gas = self.apply_eip7702_auth_list(evm)?; Ok(gas) @@ -278,6 +278,10 @@ pub trait Handler { &self, evm: &mut Self::Evm, ) -> Result<(), Self::Error> { + let caller = evm.ctx().tx().caller().into(); + let journal = evm.ctx_mut().journal_mut(); + let (_, id) = journal.load_account_code(caller)?.data; + journal.set_caller_address_id(id); pre_execution::validate_against_state_and_deduct_caller(evm.ctx()) } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 2b75a0236f..61f92d0d23 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -57,9 +57,6 @@ pub fn load_accounts< } } - let (_, id) = journal.load_account_code(tx.caller().into())?.data; - journal.set_caller_address_id(id); - // load tx target and set its id in journal. if let TxKind::Call(target) = tx.kind() { let (_, id) = journal.load_account_code(target.into())?.data; diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 78d7d9f8a3..0df83be214 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -201,11 +201,11 @@ impl JournalExt for Journal { #[inline] fn evm_state(&self) -> &EvmState { - &self.state_new + &self.state } #[inline] fn evm_state_mut(&mut self) -> &mut EvmState { - &mut self.state_new + &mut self.state } } diff --git a/crates/interpreter/src/interpreter_action/create_outcome.rs b/crates/interpreter/src/interpreter_action/create_outcome.rs index 3848206323..b54f3aca5b 100644 --- a/crates/interpreter/src/interpreter_action/create_outcome.rs +++ b/crates/interpreter/src/interpreter_action/create_outcome.rs @@ -1,5 +1,5 @@ use crate::{Gas, InstructionResult, InterpreterResult}; -use primitives::{Address, AddressAndId, Bytes}; +use primitives::{AddressAndId, Bytes}; /// Represents the outcome of a create operation in an interpreter. /// From 6006a9cc908319b0faacfb0bc8cca736de7055be Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 13 Aug 2025 01:51:34 +0200 Subject: [PATCH 23/37] check --- bins/revme/src/cmd/bench/transfer_multi.rs | 2 +- crates/context/src/journal/inner.rs | 26 +++++++++--------- crates/handler/src/pre_execution.rs | 31 ++++++++++++---------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/bins/revme/src/cmd/bench/transfer_multi.rs b/bins/revme/src/cmd/bench/transfer_multi.rs index 6c07c8cc98..d22c467677 100644 --- a/bins/revme/src/cmd/bench/transfer_multi.rs +++ b/bins/revme/src/cmd/bench/transfer_multi.rs @@ -41,7 +41,7 @@ pub fn run(criterion: &mut Criterion) { .caller(BENCH_CALLER) .kind(TxKind::Call((target + U256::from(i)).into_address())) .value(U256::from(1)) - .gas_price(1) + .gas_price(0) .gas_priority_fee(None) .gas_limit(30_000) .build() diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index b5c719240d..15cbdcb742 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -649,7 +649,7 @@ impl JournalInner { } /// Loads account. If account is already loaded it will be marked as warm. - #[inline(never)] + #[inline] pub fn load_account_optional( &mut self, db: &mut DB, @@ -658,18 +658,18 @@ impl JournalInner { storage_keys: impl IntoIterator, ) -> Result, DB::Error> { let (account, address_and_id) = match address_or_id { - AddressOrId::Address(address) => self.state.get_mut_or_fetch( - address, - |address| -> Result { - db.basic(address).map(|account| { - if let Some(account) = account { - account.into() - } else { - Account::new_not_existing(self.transaction_id) - } - }) - }, - )?, + AddressOrId::Address(address) => { + self.state + .get_mut_or_fetch(address, |address| -> Result { + db.basic(address).map(|account| { + if let Some(account) = account { + account.into() + } else { + Account::new_not_existing(self.transaction_id) + } + }) + })? + } AddressOrId::Id(id) => self.state.get_by_id_mut(id), }; diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 61f92d0d23..ab8f85e338 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -25,23 +25,11 @@ pub fn load_accounts< >( evm: &mut EVM, ) -> Result<(), ERROR> { - let beneficiary = evm.ctx().block().beneficiary().into(); - let (context, precompiles) = evm.ctx_precompiles(); - + let context = evm.ctx(); let gen_spec = context.cfg().spec(); let spec = gen_spec.clone().into(); - // sets eth spec id in journal - context.journal_mut().set_spec_id(spec); - let precompiles_changed = precompiles.set_spec(gen_spec); - let empty_warmed_precompiles = context.journal_mut().precompile_addresses().is_empty(); - if precompiles_changed || empty_warmed_precompiles { - // load new precompile addresses into journal. - // When precompiles addresses are changed we reset the warmed hashmap to those new addresses. - context - .journal_mut() - .warm_precompiles(precompiles.warm_addresses().collect()); - } + let beneficiary = context.block().beneficiary().into(); // Load access list let (tx, journal) = context.tx_journal_mut(); @@ -71,6 +59,21 @@ pub fn load_accounts< } journal.set_coinbase_address_id(id); + let (context, precompiles) = evm.ctx_precompiles(); + + // sets eth spec id in journal + context.journal_mut().set_spec_id(spec); + let precompiles_changed = precompiles.set_spec(gen_spec); + let empty_warmed_precompiles = context.journal_mut().precompile_addresses().is_empty(); + + if precompiles_changed || empty_warmed_precompiles { + // load new precompile addresses into journal. + // When precompiles addresses are changed we reset the warmed hashmap to those new addresses. + context + .journal_mut() + .warm_precompiles(precompiles.warm_addresses().collect()); + } + Ok(()) } From befdfe9c1b4e2884d80e2793479ef4e43e7f271b Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 13 Aug 2025 02:19:44 +0200 Subject: [PATCH 24/37] skip loading delegated code twice --- .../context/interface/src/journaled_state.rs | 18 ++++++++- crates/context/src/journal.rs | 6 +-- crates/context/src/journal/inner.rs | 6 +-- crates/context/src/journal/warm_addresses.rs | 10 ++++- crates/handler/src/execution.rs | 8 +++- crates/handler/src/frame.rs | 37 ++++--------------- crates/handler/src/handler.rs | 10 ++++- crates/handler/src/pre_execution.rs | 8 +++- .../interpreter/src/instructions/contract.rs | 14 ++++--- 9 files changed, 67 insertions(+), 50 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 3d416204e9..bfa1a738c1 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -145,10 +145,10 @@ pub trait JournalTr { fn caller_address_id(&self) -> Option; /// Sets the tx target address and id. - fn set_tx_target_address_id(&mut self, id: AddressAndId); + fn set_tx_target_address_id(&mut self, id: AddressAndId, delegated: Option); /// Returns the tx target address and id. - fn tx_target_address_id(&self) -> Option; + fn tx_target_address_id(&self) -> Option<(AddressAndId, Option)>; /// Loads the account delegated. fn load_account_delegated( @@ -311,3 +311,17 @@ pub struct AccountLoad { /// Does account have delegate code and delegated account is cold loaded pub delegated_account_address: Option>, } + +impl AccountLoad { + /// Returns the bytecode address. + /// + /// If the account has a delegated account, it returns the delegated account address. + /// Otherwise, it returns the account address. + pub fn bytecode_address(&self) -> AddressAndId { + if let Some(delegated_account_address) = &self.delegated_account_address { + delegated_account_address.data + } else { + self.address_and_id + } + } +} diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 3506d3d3c0..87bdd03d6e 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -152,8 +152,8 @@ impl JournalTr for Journal { } #[inline] - fn set_tx_target_address_id(&mut self, id: AddressAndId) { - self.inner.warm_addresses.set_tx_target(id); + fn set_tx_target_address_id(&mut self, id: AddressAndId, delegated: Option) { + self.inner.warm_addresses.set_tx_target(id, delegated); } #[inline] @@ -172,7 +172,7 @@ impl JournalTr for Journal { } #[inline] - fn tx_target_address_id(&self) -> Option { + fn tx_target_address_id(&self) -> Option<(AddressAndId, Option)> { self.inner.warm_addresses.tx_target() } diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 15cbdcb742..4c8447a422 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -649,7 +649,7 @@ impl JournalInner { } /// Loads account. If account is already loaded it will be marked as warm. - #[inline] + #[inline(never)] pub fn load_account_optional( &mut self, db: &mut DB, @@ -729,7 +729,7 @@ impl JournalInner { /// # Panics /// /// Panics if the account is not present in the state. - #[inline] + #[inline(never)] pub fn sload( &mut self, db: &mut DB, @@ -747,7 +747,7 @@ impl JournalInner { /// And returns (original,present,new) slot value. /// /// **Note**: Account should already be present in our state. - #[inline] + #[inline(never)] pub fn sstore( &mut self, db: &mut DB, diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs index 58ae28a763..9144b51d53 100644 --- a/crates/context/src/journal/warm_addresses.rs +++ b/crates/context/src/journal/warm_addresses.rs @@ -22,6 +22,8 @@ pub struct WarmAddresses { caller: Option, /// Tx target address and id. tx_target: Option, + /// Tx target delegated address and id. + tx_target_delegated: Option, } impl Default for WarmAddresses { @@ -41,6 +43,7 @@ impl WarmAddresses { coinbase: None, caller: None, tx_target: None, + tx_target_delegated: None, } } @@ -64,8 +67,9 @@ impl WarmAddresses { /// Returns the tx target address and id. #[inline] - pub fn tx_target(&self) -> Option { + pub fn tx_target(&self) -> Option<(AddressAndId, Option)> { self.tx_target + .map(|tx_target| (tx_target, self.tx_target_delegated)) } /// Set the precompile addresses and short addresses. @@ -101,8 +105,9 @@ impl WarmAddresses { /// Set the tx target address and id. #[inline] - pub fn set_tx_target(&mut self, address: AddressAndId) { + pub fn set_tx_target(&mut self, address: AddressAndId, delegated: Option) { self.tx_target = Some(address); + self.tx_target_delegated = delegated; } /// Clear the coinbase/caller/tx target addresses. @@ -111,6 +116,7 @@ impl WarmAddresses { self.coinbase = None; self.caller = None; self.tx_target = None; + self.tx_target_delegated = None; } /// Returns true if the address is warm loaded. diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index 34602b4732..f0dd4c0289 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -9,16 +9,22 @@ pub fn create_init_frame( is_call: bool, caller: AddressAndId, target: AddressAndId, + delegated_address: Option, input: Bytes, value: U256, gas_limit: u64, ) -> FrameInput { if is_call { + let bytecode_address = if let Some(delegated_address) = delegated_address { + delegated_address + } else { + target + }; FrameInput::Call(Box::new(CallInputs { input: CallInput::Bytes(input), gas_limit, target_address: target, - bytecode_address: target, + bytecode_address, caller: caller, value: CallValue::Transfer(value), scheme: CallScheme::Call, diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 2426c8dad5..32c4c5107b 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -162,11 +162,11 @@ impl EthFrame { return return_result(InstructionResult::CallTooDeep); } - // Make account warm and loaded. - let acc_load = ctx - .journal_mut() - .load_account_delegated(inputs.bytecode_address.to_id())? - .data; + // // Make account warm and loaded. + // let acc_load = ctx + // .journal_mut() + // .load_account_delegated(inputs.bytecode_address.to_id())? + // .data; // Create subroutine checkpoint let checkpoint = ctx.journal_mut().checkpoint(); @@ -215,30 +215,9 @@ impl EthFrame { }))); } - // let account = ctx - // .journal_mut() - // .load_account_code(inputs.bytecode_address.to_id())?; - - // let mut bytecode = account.0.info.code.clone().unwrap_or_default(); - - let (account, _) = if let Some(delegated_acc) = acc_load.delegated_account_address { - ctx.journal_mut().get_account(delegated_acc.id()) - } else { - ctx.journal_mut().get_account(acc_load.address_and_id.id()) - }; - - let code_hash = account.info.code_hash(); - let bytecode = account.info.code.clone().unwrap_or_default(); - - // if let Bytecode::Eip7702(eip7702_bytecode) = bytecode { - // let account = &ctx - // .journal_mut() - // .load_account_code(eip7702_bytecode.delegated_address.into())? - // .0 - // .info; - // bytecode = account.code.clone().unwrap_or_default(); - // code_hash = account.code_hash(); - // } + let (bytecode_account, _) = ctx.journal_mut().get_account(inputs.bytecode_address.id()); + let code_hash = bytecode_account.info.code_hash(); + let bytecode = bytecode_account.info.code.clone().unwrap_or_default(); // Returns success if bytecode is empty. if bytecode.is_empty() { diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index facedf58a6..046832032a 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -299,7 +299,7 @@ pub trait Handler { let ctx = evm.ctx_ref(); let caller = ctx.journal().caller_address_id().expect("caller id is set"); - let target = ctx + let (target, delegated_address) = ctx .journal() .tx_target_address_id() .expect("tx target id is set"); @@ -311,7 +311,13 @@ pub trait Handler { depth: 0, memory, frame_input: execution::create_init_frame( - is_call, caller, target, input, value, gas_limit, + is_call, + caller, + target, + delegated_address, + input, + value, + gas_limit, ), }) } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index ab8f85e338..b06567f918 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -19,6 +19,7 @@ use state::AccountInfo; use std::boxed::Box; /// Loads and warms accounts for execution, including precompiles and access list. +#[inline] pub fn load_accounts< EVM: EvmTr>, ERROR: From<<::Db as Database>::Error>, @@ -47,8 +48,11 @@ pub fn load_accounts< // load tx target and set its id in journal. if let TxKind::Call(target) = tx.kind() { - let (_, id) = journal.load_account_code(target.into())?.data; - journal.set_tx_target_address_id(id); + let acc = journal.load_account_delegated(target.into())?.data; + journal.set_tx_target_address_id( + acc.address_and_id, + acc.delegated_account_address.map(|a| a.data), + ); } let (coinbase, id) = journal.load_account_code(beneficiary)?.data; diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 53cd798364..be45a0d69c 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -134,6 +134,7 @@ pub fn call(context: InstructionContex return; }; let to = account_load.address_and_id; + let bytecode_address = account_load.bytecode_address(); let Some(mut gas_limit) = calc_call_gas( context.interpreter, @@ -161,7 +162,7 @@ pub fn call(context: InstructionContex gas_limit, target_address: to, caller: context.interpreter.input.target_address(), - bytecode_address: to, + bytecode_address, value: CallValue::Transfer(value), scheme: CallScheme::Call, is_static: context.interpreter.runtime_flag.is_static(), @@ -193,7 +194,7 @@ pub fn call_code( .halt(InstructionResult::FatalExternalError); return; }; - let to = load.address_and_id; + let bytecode_address = load.bytecode_address(); // Set `is_empty` to false as we are not creating this account. load.is_empty = false; @@ -220,7 +221,7 @@ pub fn call_code( gas_limit, target_address: context.interpreter.input.target_address(), caller: context.interpreter.input.target_address(), - bytecode_address: to, + bytecode_address, value: CallValue::Transfer(value), scheme: CallScheme::CallCode, is_static: context.interpreter.runtime_flag.is_static(), @@ -252,7 +253,7 @@ pub fn delegate_call( .halt(InstructionResult::FatalExternalError); return; }; - let to = load.address_and_id; + let bytecode_address = load.bytecode_address(); // Set is_empty to false as we are not creating this account. load.is_empty = false; @@ -272,7 +273,7 @@ pub fn delegate_call( gas_limit, target_address: context.interpreter.input.target_address(), caller: context.interpreter.input.caller_address(), - bytecode_address: to, + bytecode_address, value: CallValue::Apparent(context.interpreter.input.call_value()), scheme: CallScheme::DelegateCall, is_static: context.interpreter.runtime_flag.is_static(), @@ -305,6 +306,7 @@ pub fn static_call( return; }; let to = load.address_and_id; + let bytecode_address = load.bytecode_address(); // Set `is_empty` to false as we are not creating this account. load.is_empty = false; @@ -323,7 +325,7 @@ pub fn static_call( gas_limit, target_address: to, caller: context.interpreter.input.target_address(), - bytecode_address: to, + bytecode_address, value: CallValue::Transfer(U256::ZERO), scheme: CallScheme::StaticCall, is_static: true, From 33537f6e7e86d8f7883528cea054fb05cc74673c Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 13 Aug 2025 02:36:51 +0200 Subject: [PATCH 25/37] local sload in sstore --- crates/context/src/journal/inner.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 4c8447a422..aa54d59e97 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -756,11 +756,14 @@ impl JournalInner { new: StorageValue, ) -> Result, DB::Error> { // assume that acc exists and load the slot. - let present = self.sload(db, address_or_id, key)?; - let (acc, id) = self.state.get_mut(address_or_id).unwrap(); + + let (account, id) = self.state.get_mut(address_or_id).unwrap(); + // only if account is created in this tx we can assume that storage is empty. + let present = + sload_with_account(account, db, &mut self.journal, self.transaction_id, id, key)?; // if there is no original value in dirty return present value, that is our original. - let slot = acc.storage.get_mut(&key).unwrap(); + let slot = account.storage.get_mut(&key).unwrap(); // new value is same as present, we don't need to do anything if present.data == new { From 90f941915b22afe13938df0489c80b1bd7a3fa95 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 13 Aug 2025 02:46:15 +0200 Subject: [PATCH 26/37] sload --- crates/context/src/journal/inner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index aa54d59e97..45192329c5 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -729,7 +729,7 @@ impl JournalInner { /// # Panics /// /// Panics if the account is not present in the state. - #[inline(never)] + #[inline] pub fn sload( &mut self, db: &mut DB, From 64c00919373f3cf171cfa9d3c7d1f69021e068cf Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 13 Aug 2025 12:51:29 +0200 Subject: [PATCH 27/37] no_std support --- crates/handler/src/frame.rs | 6 ------ crates/state/src/lib.rs | 3 +++ crates/state/src/types.rs | 1 + 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 32c4c5107b..a0b62dc3b8 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -162,12 +162,6 @@ impl EthFrame { return return_result(InstructionResult::CallTooDeep); } - // // Make account warm and loaded. - // let acc_load = ctx - // .journal_mut() - // .load_account_delegated(inputs.bytecode_address.to_id())? - // .data; - // Create subroutine checkpoint let checkpoint = ctx.journal_mut().checkpoint(); diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index ce64646ea8..37b8dd55ac 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -2,6 +2,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(not(feature = "std"))] +extern crate alloc as std; + mod account; mod account_info; mod storage; diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 608d070ca3..8e2140ea57 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -1,4 +1,5 @@ use crate::{Account, EvmStorageSlot}; +use std::{vec, vec::Vec}; use primitives::{ map::Entry, AccountId, Address, AddressAndId, AddressOrId, HashMap, StorageKey, StorageValue, }; From 25ed180c89c466e6a07c2f30ee9c7e4938c190b9 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 02:48:17 +0200 Subject: [PATCH 28/37] clippy fmt --- crates/handler/src/execution.rs | 2 +- crates/handler/src/frame.rs | 2 +- crates/interpreter/src/instructions/contract.rs | 14 +++++++------- crates/state/src/account.rs | 2 +- crates/state/src/storage.rs | 2 +- crates/state/src/types.rs | 9 ++++----- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index f0dd4c0289..9287c6ad3e 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -25,7 +25,7 @@ pub fn create_init_frame( gas_limit, target_address: target, bytecode_address, - caller: caller, + caller, value: CallValue::Transfer(value), scheme: CallScheme::Call, is_static: false, diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index a0b62dc3b8..7b27d7ca22 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -191,7 +191,7 @@ impl EthFrame { if let Some(result) = precompiles .run( ctx, - &inputs.bytecode_address.address(), + inputs.bytecode_address.address(), &interpreter_input, is_static, gas_limit, diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index be45a0d69c..ae6d5e11c5 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -107,7 +107,7 @@ pub fn create( /// Message call with value transfer to another account. pub fn call(context: InstructionContext<'_, H, WIRE>) { popn!([local_gas_limit, to, value], context.interpreter); - let to = to.into_address().into(); + let to = to.into_address(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -178,7 +178,7 @@ pub fn call_code( context: InstructionContext<'_, H, WIRE>, ) { popn!([local_gas_limit, to, value], context.interpreter); - let to = to.into_address().into(); + let to = to.into_address(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -188,7 +188,7 @@ pub fn call_code( return; }; - let Some(mut load) = context.host.load_account_delegated(to) else { + let Some(mut load) = context.host.load_account_delegated(to.into()) else { context .interpreter .halt(InstructionResult::FatalExternalError); @@ -238,7 +238,7 @@ pub fn delegate_call( ) { check!(context.interpreter, HOMESTEAD); popn!([local_gas_limit, to], context.interpreter); - let to = to.into_address().into(); + let to = to.into_address(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -247,7 +247,7 @@ pub fn delegate_call( return; }; - let Some(mut load) = context.host.load_account_delegated(to) else { + let Some(mut load) = context.host.load_account_delegated(to.into()) else { context .interpreter .halt(InstructionResult::FatalExternalError); @@ -290,7 +290,7 @@ pub fn static_call( ) { check!(context.interpreter, BYZANTIUM); popn!([local_gas_limit, to], context.interpreter); - let to = to.into_address().into(); + let to = to.into_address(); // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); @@ -299,7 +299,7 @@ pub fn static_call( return; }; - let Some(mut load) = context.host.load_account_delegated(to) else { + let Some(mut load) = context.host.load_account_delegated(to.into()) else { context .interpreter .halt(InstructionResult::FatalExternalError); diff --git a/crates/state/src/account.rs b/crates/state/src/account.rs index 3464c37e28..df182337a6 100644 --- a/crates/state/src/account.rs +++ b/crates/state/src/account.rs @@ -102,7 +102,7 @@ impl Account { let is_cold = self.status.contains(AccountStatus::Cold); self.status -= AccountStatus::Cold; - (same_id && is_cold) || !same_id + !same_id || is_cold } /// Is account locally created diff --git a/crates/state/src/storage.rs b/crates/state/src/storage.rs index 490e496cd1..8ebda98736 100644 --- a/crates/state/src/storage.rs +++ b/crates/state/src/storage.rs @@ -73,7 +73,7 @@ impl EvmStorageSlot { self.transaction_id = transaction_id; let was_cold = core::mem::take(&mut self.is_cold); // only if transaction id is same we are returning was_cold. - (same_id && was_cold) || !same_id + !same_id || was_cold } } diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 8e2140ea57..4abab77239 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -1,8 +1,8 @@ use crate::{Account, EvmStorageSlot}; -use std::{vec, vec::Vec}; use primitives::{ map::Entry, AccountId, Address, AddressAndId, AddressOrId, HashMap, StorageKey, StorageValue, }; +use std::{vec, vec::Vec}; /// Structure used for EIP-1153 transient storage pub type TransientStorage = HashMap<(AccountId, StorageKey), StorageValue>; @@ -58,8 +58,7 @@ impl EvmState { AddressOrId::Address(address) => self.index.get(&address).and_then(|id| { self.accounts .get_mut(id.0 as usize) - .map(|accounts| accounts.get_mut(id.1 as usize)) - .flatten() + .and_then(|accounts| accounts.get_mut(id.1 as usize)) .map(|(acc, address)| (acc, AddressAndId::new(*address, *id))) }), } @@ -174,7 +173,7 @@ fn push_account( /// Get a mutable reference to an account by id. #[inline] fn get_by_id_mut( - accounts: &mut Vec>, + accounts: &mut [Vec<(Account, Address)>], id: AccountId, ) -> (&mut Account, AddressAndId) { let account = unsafe { @@ -187,7 +186,7 @@ fn get_by_id_mut( /// Get an immutable reference to an account by id. #[inline] -fn get_by_id(accounts: &Vec>, id: AccountId) -> (&Account, AddressAndId) { +fn get_by_id(accounts: &[Vec<(Account, Address)>], id: AccountId) -> (&Account, AddressAndId) { let account = unsafe { accounts .get_unchecked(id.0 as usize) From 1ef32b1d9670fef089c407137e8716d6f392bdca Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 03:42:49 +0200 Subject: [PATCH 29/37] paging first page, tests --- crates/database/src/in_memory_db.rs | 4 +- crates/database/src/states/cache.rs | 7 +- crates/handler/src/execution.rs | 6 +- crates/handler/src/handler.rs | 17 +- crates/state/src/lib.rs | 2 +- crates/state/src/types.rs | 352 ++++++++++++++++++++++++++-- 6 files changed, 348 insertions(+), 40 deletions(-) diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index 4f95b57358..ab09a1aaf1 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -191,8 +191,8 @@ impl CacheDB { } impl DatabaseCommit for CacheDB { - fn commit(&mut self, changes: EvmState) { - for (mut account, address) in changes.accounts.into_iter().flatten() { + fn commit(&mut self, mut changes: EvmState) { + for (mut account, address) in changes.take_accounts().into_iter().flatten() { if !account.is_touched() { continue; } diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index 6e9d74465e..307bc2368d 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -89,9 +89,12 @@ impl CacheState { } /// Applies output of revm execution and create account transitions that are used to build BundleState. - pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> { + pub fn apply_evm_state( + &mut self, + mut evm_state: EvmState, + ) -> Vec<(Address, TransitionAccount)> { let mut transitions = Vec::with_capacity(evm_state.len()); - for (account, address) in evm_state.accounts.into_iter().flatten() { + for (account, address) in evm_state.take_accounts().into_iter().flatten() { if let Some(transition) = self.apply_account_state(address, account) { transitions.push((address, transition)); } diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index 9287c6ad3e..f769cc80f1 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -6,15 +6,13 @@ use std::boxed::Box; /// Creates the first [`FrameInput`] from the transaction, spec and gas limit. pub fn create_init_frame( - is_call: bool, caller: AddressAndId, - target: AddressAndId, - delegated_address: Option, + target: Option<(AddressAndId, Option)>, input: Bytes, value: U256, gas_limit: u64, ) -> FrameInput { - if is_call { + if let Some((target, delegated_address)) = target { let bytecode_address = if let Some(delegated_address) = delegated_address { delegated_address } else { diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 046832032a..043bb2eaaf 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -299,26 +299,15 @@ pub trait Handler { let ctx = evm.ctx_ref(); let caller = ctx.journal().caller_address_id().expect("caller id is set"); - let (target, delegated_address) = ctx - .journal() - .tx_target_address_id() - .expect("tx target id is set"); + // if tx is not call target will be None. + let target = ctx.journal().tx_target_address_id(); let tx = ctx.tx(); let input = tx.input().clone(); let value = tx.value(); - let is_call = tx.kind().is_call(); Ok(FrameInit { depth: 0, memory, - frame_input: execution::create_init_frame( - is_call, - caller, - target, - delegated_address, - input, - value, - gas_limit, - ), + frame_input: execution::create_init_frame(caller, target, input, value, gas_limit), }) } diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 37b8dd55ac..94d9d0f645 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -15,4 +15,4 @@ pub use account_info::AccountInfo; pub use bytecode::{self, Bytecode}; pub use primitives; pub use storage::EvmStorageSlot; -pub use types::{EvmState, EvmStorage, TransientStorage}; +pub use types::{AccountPages, EvmState, EvmStorage, TransientStorage}; diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index 4abab77239..bb57734f9c 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -10,15 +10,24 @@ pub type TransientStorage = HashMap<(AccountId, StorageKey), StorageValue>; /// An account's Storage is a mapping from 256-bit integer keys to [EvmStorageSlot]s. pub type EvmStorage = HashMap; +/// First page size is 3 to account for Caller, Target, and Beneficiary. +const FIRST_PAGE_SIZE: usize = 3; + +/// Page size is 100. +const PAGE_SIZE: usize = 100; + +/// Pages of accounts. +pub type AccountPages = Vec>; + /// EVM State with internal account management. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EvmState { /// Index of accounts. - pub index: HashMap, + index: HashMap, /// Accounts. /// TODO make pushing of new account smarter and introduce a Vec of Vec so we dont need to clone it. - pub accounts: Vec>, + accounts: AccountPages, } impl EvmState { @@ -26,11 +35,57 @@ impl EvmState { pub fn new() -> Self { Self { index: HashMap::default(), - // Allocate first with 3 account (Caller, target, beneficiary) - accounts: vec![Vec::with_capacity(3)], + accounts: vec![Vec::with_capacity(FIRST_PAGE_SIZE)], } } + /// Return pages of accounts. + #[inline] + pub fn accounts(&self) -> &AccountPages { + &self.accounts + } + + /// Return mutable reference to accounts. + #[inline] + pub fn accounts_mut(&mut self) -> &mut AccountPages { + &mut self.accounts + } + + /// Take accounts. + #[inline] + pub fn take(&mut self) -> (AccountPages, HashMap) { + let accounts = std::mem::replace( + &mut self.accounts, + vec![Vec::with_capacity(FIRST_PAGE_SIZE)], + ); + let index = std::mem::take(&mut self.index); + (accounts, index) + } + + /// Take accounts. + #[inline] + pub fn take_accounts(&mut self) -> AccountPages { + self.take().0 + } + + /// Take index. + #[inline] + pub fn take_index(&mut self) -> HashMap { + self.take().1 + } + + /// Return index of accounts. + #[inline] + pub fn index(&self) -> &HashMap { + &self.index + } + + /// Return mutable reference to index. + #[inline] + pub fn index_mut(&mut self) -> &mut HashMap { + &mut self.index + } + /// Get the account id for an address or id. pub fn get_id(&self, address_or_id: &AddressOrId) -> Option { match address_or_id { @@ -86,10 +141,8 @@ impl EvmState { AddressAndId::new(address, id) } None => { - // TODO Fix this - let id = (self.accounts.len() as u32, 0); + let id = push_account(&mut self.accounts, account, address); self.index.insert(address, id); - self.accounts.push(vec![(account, address)]); AddressAndId::new(address, id) } } @@ -151,23 +204,20 @@ impl EvmState { /// /// Returns the account id that was assigned to the account. #[inline] -fn push_account( - accounts: &mut Vec>, - account: Account, - address: Address, -) -> AccountId { - let page_id = accounts.len() as u32; +fn push_account(accounts: &mut AccountPages, account: Account, address: Address) -> AccountId { + let page_len = accounts.len() as u32; if let Some(last) = accounts.last_mut() { - if last.len() < 100 { - let id = (page_id - 1, last.len() as u32); + let last_len = last.len(); + if (page_len == 1 && last_len < FIRST_PAGE_SIZE) || (page_len > 1 && last_len < PAGE_SIZE) { + let id = (page_len - 1, last_len as u32); last.push((account, address)); return id; } } - let mut vec = Vec::with_capacity(100); + let mut vec = Vec::with_capacity(PAGE_SIZE); vec.push((account, address)); accounts.push(vec); - (page_id, 0) + (page_len, 0) } /// Get a mutable reference to an account by id. @@ -210,3 +260,271 @@ impl From> for EvmState { state } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{AccountInfo, AccountStatus}; + + fn create_test_account(nonce: u64) -> Account { + Account { + info: AccountInfo { + balance: primitives::U256::from(1000), + nonce, + code_hash: primitives::KECCAK_EMPTY, + code: None, + }, + storage: HashMap::default(), + status: AccountStatus::empty(), + transaction_id: 0, + } + } + + #[test] + fn test_get_mut_or_fetch_existing_account() { + let mut state = EvmState::new(); + let address = Address::from([0x01; 20]); + let account = create_test_account(1); + + // Insert an account + let id = state.insert(address, account.clone()); + + // Fetch existing account - should not call the fetch function + let result: Result<_, &str> = state.get_mut_or_fetch(address, |_| { + panic!("Fetch function should not be called for existing account"); + }); + + assert!(result.is_ok()); + let (fetched_account, fetched_id) = result.unwrap(); + assert_eq!(fetched_account.info.nonce, 1); + assert_eq!(*fetched_id.address(), address); + assert_eq!(fetched_id.id(), id.id()); + } + + #[test] + fn test_get_mut_or_fetch_new_account() { + let mut state = EvmState::new(); + let address = Address::from([0x02; 20]); + + // Fetch new account - should call the fetch function + let mut fetch_called = false; + let result: Result<_, &str> = state.get_mut_or_fetch(address, |addr| { + fetch_called = true; + assert_eq!(addr, address); + Ok(create_test_account(42)) + }); + + assert!(fetch_called); + assert!(result.is_ok()); + + let (fetched_account, fetched_id) = result.unwrap(); + assert_eq!(fetched_account.info.nonce, 42); + assert_eq!(*fetched_id.address(), address); + assert_eq!(fetched_id.id(), (0, 0)); + + // Verify account was added to state + assert!(state.contains_key(&address)); + assert_eq!(state.len(), 1); + } + + #[test] + fn test_get_mut_or_fetch_error_propagation() { + let mut state = EvmState::new(); + let address = Address::from([0x03; 20]); + + // Test error propagation + let result = state.get_mut_or_fetch(address, |_| Err::("fetch error")); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "fetch error"); + + // Verify account was not added to state + assert!(!state.contains_key(&address)); + assert_eq!(state.len(), 0); + } + + #[test] + fn test_get_mut_or_fetch_mutability() { + let mut state = EvmState::new(); + let address = Address::from([0x04; 20]); + + // Fetch and modify new account + let result: Result<_, &str> = + state.get_mut_or_fetch(address, |_| Ok(create_test_account(10))); + assert!(result.is_ok()); + + let (account, _) = result.unwrap(); + account.info.nonce = 20; + + // Verify modification persisted + let (account, _) = state.get(AddressOrId::Address(address)).unwrap(); + assert_eq!(account.info.nonce, 20); + } + + #[test] + fn test_get_mut_or_fetch_multiple_accounts() { + let mut state = EvmState::new(); + let address1 = Address::from([0x05; 20]); + let address2 = Address::from([0x06; 20]); + let address3 = Address::from([0x07; 20]); + let address4 = Address::from([0x08; 20]); + + // Add first account + state.insert(address1, create_test_account(1)); + + // Fetch existing and new accounts + let result1: Result<_, ()> = + state.get_mut_or_fetch(address1, |_| panic!("Should not fetch existing account")); + assert!(result1.is_ok()); + assert_eq!(result1.unwrap().1.id(), (0, 0)); + + let result2: Result<_, ()> = + state.get_mut_or_fetch(address2, |_| Ok(create_test_account(2))); + assert!(result2.is_ok()); + assert_eq!(result2.unwrap().1.id(), (0, 1)); + + let result3: Result<_, ()> = + state.get_mut_or_fetch(address3, |_| Ok(create_test_account(3))); + assert!(result3.is_ok()); + assert_eq!(result3.unwrap().1.id(), (0, 2)); + + let result4: Result<_, ()> = + state.get_mut_or_fetch(address4, |_| Ok(create_test_account(4))); + assert!(result4.is_ok()); + assert_eq!(result4.unwrap().1.id(), (1, 0)); + + // Verify all accounts are in state + assert_eq!(state.len(), 4); + assert!(state.contains_key(&address1)); + assert!(state.contains_key(&address2)); + assert!(state.contains_key(&address3)); + assert!(state.contains_key(&address4)); + } + + #[test] + fn test_pagination_behavior() { + let mut state = EvmState::new(); + let mut addresses = Vec::new(); + + // Add more than 100 accounts to test pagination + for i in 0..150 { + let mut bytes = [0u8; 20]; + bytes[19] = i as u8; + let address = Address::from(bytes); + addresses.push(address); + let _: Result<_, &str> = + state.get_mut_or_fetch(address, |_| Ok(create_test_account(i as u64))); + } + + // Verify all accounts are accessible + assert_eq!(state.len(), 150); + for (i, address) in addresses.iter().enumerate() { + let (account, _) = state.get(AddressOrId::Address(*address)).unwrap(); + assert_eq!(account.info.nonce, i as u64); + } + + // Verify pagination structure + assert!(state.accounts.len() >= 2); // Should have at least 2 pages + assert_eq!(state.accounts[0].len(), 100); // First page should be full + } + + #[test] + fn test_get_by_id_and_address() { + let mut state = EvmState::new(); + let address = Address::from([0x08; 20]); + + // Insert account and get its ID + let id_info = state.insert(address, create_test_account(99)); + let id = id_info.id(); + + // Test get by ID + let (account_by_id, addr_id) = state.get_by_id(id); + assert_eq!(account_by_id.info.nonce, 99); + assert_eq!(*addr_id.address(), address); + assert_eq!(addr_id.id(), id); + + // Test get by address + let (account_by_addr, addr_id2) = state.get(AddressOrId::Address(address)).unwrap(); + assert_eq!(account_by_addr.info.nonce, 99); + assert_eq!(addr_id2, addr_id); + + // Test get_mut by ID + let (account_mut_by_id, _) = state.get_by_id_mut(id); + account_mut_by_id.info.nonce = 100; + + // Verify modification + let (account, _) = state.get_by_id(id); + assert_eq!(account.info.nonce, 100); + } + + #[test] + fn test_insert_update_existing() { + let mut state = EvmState::new(); + let address = Address::from([0x09; 20]); + + // Initial insert + let id1 = state.insert(address, create_test_account(1)); + assert_eq!(state.len(), 1); + + // Update existing account + let id2 = state.insert(address, create_test_account(2)); + assert_eq!(state.len(), 1); // Length should not change + assert_eq!(id1.id(), id2.id()); // ID should remain the same + + // Verify update + let (account, _) = state.get(AddressOrId::Address(address)).unwrap(); + assert_eq!(account.info.nonce, 2); + } + + #[test] + fn test_clear_and_is_empty() { + let mut state = EvmState::new(); + assert!(state.is_empty()); + + // Add some accounts + for i in 0..5 { + let mut bytes = [0u8; 20]; + bytes[19] = i as u8; + let address = Address::from(bytes); + state.insert(address, create_test_account(i)); + } + + assert!(!state.is_empty()); + assert_eq!(state.len(), 5); + + // Clear state + state.clear(); + assert!(state.is_empty()); + assert_eq!(state.len(), 0); + assert_eq!(state.accounts.len(), 0); + } + + #[test] + fn test_iter() { + let mut state = EvmState::new(); + let mut expected_addresses = Vec::new(); + + // Add accounts + for i in 0..10 { + let mut bytes = [0u8; 20]; + bytes[19] = i as u8; + let address = Address::from(bytes); + expected_addresses.push(address); + state.insert(address, create_test_account(i)); + } + + // Iterate and collect + let collected: Vec<_> = state.iter().collect(); + assert_eq!(collected.len(), 10); + + // Verify all addresses are present + for (account, address) in collected { + assert!(expected_addresses.contains(&address)); + let index = expected_addresses + .iter() + .position(|&a| a == *address) + .unwrap(); + assert_eq!(account.info.nonce, index as u64); + } + } +} From 71c91ca581e0629489ddf68c1db8a6d39394288a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 04:06:11 +0200 Subject: [PATCH 30/37] some fixes --- crates/context/src/journal/entry.rs | 1 - crates/context/src/journal/inner.rs | 8 +++++--- crates/handler/src/pre_execution.rs | 2 ++ crates/state/src/account.rs | 4 ++-- crates/state/src/types.rs | 8 ++------ 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/crates/context/src/journal/entry.rs b/crates/context/src/journal/entry.rs index 0412a81644..9aa3dfb53f 100644 --- a/crates/context/src/journal/entry.rs +++ b/crates/context/src/journal/entry.rs @@ -403,7 +403,6 @@ impl JournalEntryTr for JournalEntry { // if not zero, reinsert old value to transient storage. transient_storage.insert(tkey, had_value); } - todo!() } JournalEntry::CodeChange { account_id } => { let (acc, _) = state.get_mut(account_id.into()).unwrap(); diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 45192329c5..eb21f7dd84 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -15,7 +15,7 @@ use primitives::{ AccountId, Address, AddressAndId, AddressOrId, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; -use state::{Account, EvmState, EvmStorageSlot, TransientStorage}; +use state::{Account, AccountStatus, EvmState, EvmStorageSlot, TransientStorage}; use std::vec::Vec; /// Inner journal state that contains journal and state changes. /// @@ -662,11 +662,13 @@ impl JournalInner { self.state .get_mut_or_fetch(address, |address| -> Result { db.basic(address).map(|account| { - if let Some(account) = account { + let mut account = if let Some(account) = account { account.into() } else { Account::new_not_existing(self.transaction_id) - } + }; + account.status |= AccountStatus::Cold; + account }) })? } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index b06567f918..a4eabd56d6 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -60,6 +60,8 @@ pub fn load_accounts< // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm if spec.is_enabled_in(SpecId::SHANGHAI) { coinbase.mark_touch(); + } else { + coinbase.mark_cold(); } journal.set_coinbase_address_id(id); diff --git a/crates/state/src/account.rs b/crates/state/src/account.rs index df182337a6..3af3ad953a 100644 --- a/crates/state/src/account.rs +++ b/crates/state/src/account.rs @@ -97,12 +97,12 @@ impl Account { /// Marks the account as warm and return true if it was previously cold. #[inline] pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { - let same_id = self.transaction_id == transaction_id; + let diff_id = self.transaction_id != transaction_id; self.transaction_id = transaction_id; let is_cold = self.status.contains(AccountStatus::Cold); self.status -= AccountStatus::Cold; - !same_id || is_cold + diff_id || is_cold } /// Is account locally created diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index bb57734f9c..ad666251f9 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -11,7 +11,7 @@ pub type TransientStorage = HashMap<(AccountId, StorageKey), StorageValue>; pub type EvmStorage = HashMap; /// First page size is 3 to account for Caller, Target, and Beneficiary. -const FIRST_PAGE_SIZE: usize = 3; +const FIRST_PAGE_SIZE: usize = 10; /// Page size is 100. const PAGE_SIZE: usize = 100; @@ -190,11 +190,7 @@ impl EvmState { let account = fetch(address)?; let id = push_account(&mut self.accounts, account, address); entry.insert(id); - let address_and_id = AddressAndId::new(address, id); - Ok(( - &mut self.accounts.last_mut().unwrap().last_mut().unwrap().0, - address_and_id, - )) + Ok(get_by_id_mut(&mut self.accounts, id)) } } } From fc75b6c97417fbb6a241669a6d3c7550e5e47667 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 13:48:46 +0200 Subject: [PATCH 31/37] fix system call load --- .../op_revm_testdata/test_deposit_tx.json | 57 +-- .../test_halted_deposit_tx.json | 146 +++++--- ...all_bls12_381_g1_add_input_wrong_size.json | 271 +++++++++------ ...d_tx_call_bls12_381_g1_add_out_of_gas.json | 271 +++++++++------ ...all_bls12_381_g1_msm_input_wrong_size.json | 271 +++++++++------ ...d_tx_call_bls12_381_g1_msm_out_of_gas.json | 271 +++++++++------ ...l_bls12_381_g1_msm_wrong_input_layout.json | 271 +++++++++------ ...all_bls12_381_g2_add_input_wrong_size.json | 271 +++++++++------ ...d_tx_call_bls12_381_g2_add_out_of_gas.json | 271 +++++++++------ ...all_bls12_381_g2_msm_input_wrong_size.json | 271 +++++++++------ ...d_tx_call_bls12_381_g2_msm_out_of_gas.json | 271 +++++++++------ ...l_bls12_381_g2_msm_wrong_input_layout.json | 271 +++++++++------ ...12_381_map_fp2_to_g2_input_wrong_size.json | 271 +++++++++------ ...ll_bls12_381_map_fp2_to_g2_out_of_gas.json | 271 +++++++++------ ...s12_381_map_fp_to_g1_input_wrong_size.json | 271 +++++++++------ ...all_bls12_381_map_fp_to_g1_out_of_gas.json | 271 +++++++++------ ...ll_bls12_381_pairing_input_wrong_size.json | 271 +++++++++------ ..._tx_call_bls12_381_pairing_out_of_gas.json | 271 +++++++++------ ..._bls12_381_pairing_wrong_input_layout.json | 271 +++++++++------ .../test_halted_tx_call_bn254_pair_fjord.json | 271 +++++++++------ ...est_halted_tx_call_bn254_pair_granite.json | 271 +++++++++------ .../test_halted_tx_call_p256verify.json | 271 +++++++++------ .../op_revm_testdata/test_log_inspector.json | 328 ++++++++++-------- .../op_revm_testdata/test_system_call.json | 165 --------- .../test_tx_call_p256verify.json | 271 +++++++++------ .../revm_testdata/test_multi_tx_create.json | 222 +++++++----- .../test_selfdestruct_multi_tx.json | 218 +++++++----- crates/handler/src/handler.rs | 18 +- crates/inspector/src/count_inspector.rs | 1 + crates/inspector/src/gas.rs | 1 + crates/inspector/src/handler.rs | 16 + crates/inspector/src/noop.rs | 1 + crates/op-revm/src/handler.rs | 13 +- crates/state/src/types.rs | 8 +- src/lib.rs | 0 temp.json | 118 +++++++ 36 files changed, 4045 insertions(+), 2958 deletions(-) delete mode 100644 crates/ee-tests/tests/op_revm_testdata/test_system_call.json create mode 100644 src/lib.rs create mode 100644 temp.json diff --git a/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json index ce989e10db..69da0bcb01 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json @@ -11,30 +11,43 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x64", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x64", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json index 0769dd9c2f..b13122415e 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json @@ -6,57 +6,109 @@ } }, "state": { - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { - "info": { - "balance": "0x2386f26fc10064", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x2386f26fc10064", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched", - "storage": {}, - "transaction_id": 0 - }, - "0xffffffffffffffffffffffffffffffffffffffff": { - "info": { - "balance": "0x2386f26fc10000", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x5000", - "jump_table": { - "bits": 1, - "data": [ - 0 - ], - "head": { - "index": 0, - "width": 8 + "status": "Touched", + "storage": {}, + "transaction_id": 0 + }, + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + ], + [ + { + "info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x5000", + "jump_table": { + "bits": 1, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 1 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0x7b2ab94bb7d45041581aa3757ae020084674ccad6f75dc3750eb2ea8a92c4e9a", + "nonce": 1 }, - "original_len": 1 - } - }, - "code_hash": "0x7b2ab94bb7d45041581aa3757ae020084674ccad6f75dc3750eb2ea8a92c4e9a", - "nonce": 1 - }, - "status": "Cold", - "storage": {}, - "transaction_id": 0 + "status": "Cold", + "storage": {}, + "transaction_id": 0 + }, + "0xffffffffffffffffffffffffffffffffffffffff" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting | Cold", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 2 + ], + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + 0, + 0 + ], + "0xffffffffffffffffffffffffffffffffffffffff": [ + 0, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json index 91cea8ca54..97f5cc76ac 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000b" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000b": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json index 4d1f78ca80..7f5f12b305 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000b" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000b": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json index 5fdee80453..596ca18e1a 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000c": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000c" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000c": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json index d2a41cfed6..2b07a15074 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000c": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000c" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000c": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json index 5fdee80453..596ca18e1a 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000c": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000c" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000c": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json index b2970ea9cb..625079925d 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000d": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000d" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000d": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json index c050e75ec1..db52fbc922 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000d": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000d" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000d": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json index 4ef0718ec2..661ead54ed 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000e": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000e" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000e": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json index 59b81d7b5e..e02d7c5e55 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000e": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000e" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000e": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json index 4ef0718ec2..661ead54ed 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000e": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000e" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000e": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json index 311e0b6a77..4ab70d8fa3 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000011": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000011" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000011": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json index 4e12839026..f8de467477 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000011": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000011" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000011": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json index 1b768b6653..21873b2548 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000010": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000010" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000010": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json index cc66059ecf..b6b3ed998c 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000010": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000010" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000010": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json index b650e8b8f1..e21517d30a 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000f": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000f" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000f": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json index e3ecc1304f..ded93ca2a5 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000f": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000f" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000f": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json index b650e8b8f1..e21517d30a 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x000000000000000000000000000000000000000f": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000000f" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x000000000000000000000000000000000000000f": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json index 4f98b9d9ad..c08e193ba6 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000008": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000008" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000008": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json index 85591e9afa..8634a11fb3 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json @@ -8,130 +8,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000008": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000008" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000008": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json index a21e7ce5e3..3a5eb04c33 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json @@ -10,130 +10,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000100": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000100" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000100": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json index 145505a365..ecb2e13523 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json @@ -17,157 +17,207 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched", + "storage": {}, + "transaction_id": 0 + }, + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + ], + [ + { + "info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x600080a000", + "jump_table": { + "bits": 5, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 5 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0x8013c386d5a03c3fa0a6ccbfefcf7d91471dedba2bb94eefef57f916e5929a8d", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched", + "storage": {}, + "transaction_id": 0 + }, + "0xffffffffffffffffffffffffffffffffffffffff" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting | Cold", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { - "info": { - "balance": "0x2386f26fc10000", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched", - "storage": {}, - "transaction_id": 0 - }, - "0xffffffffffffffffffffffffffffffffffffffff": { - "info": { - "balance": "0x2386f26fc10000", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x600080a000", - "jump_table": { - "bits": 5, - "data": [ - 0 - ], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 5 - } - }, - "code_hash": "0x8013c386d5a03c3fa0a6ccbfefcf7d91471dedba2bb94eefef57f916e5929a8d", - "nonce": 1 - }, - "status": "Touched", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 2 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 1 + ], + "0x420000000000000000000000000000000000001a": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 2 + ], + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + 0, + 0 + ], + "0xffffffffffffffffffffffffffffffffffffffff": [ + 0, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_system_call.json b/crates/ee-tests/tests/op_revm_testdata/test_system_call.json deleted file mode 100644 index eb8f4e1a10..0000000000 --- a/crates/ee-tests/tests/op_revm_testdata/test_system_call.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "result": { - "Success": { - "gas_refunded": 0, - "gas_used": 21020, - "logs": [], - "output": { - "Call": "0x" - }, - "reason": "Stop" - } - }, - "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0xfffffffffffffffffffffffffffffffffffffffe": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0xffffffffffffffffffffffffffffffffffffffff": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - } - } -} \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json index 87cdf23853..69c9ca9105 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json @@ -11,130 +11,173 @@ } }, "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000000100": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000000100" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 0 + ], + "0x0000000000000000000000000000000000000100": [ + 0, + 1 + ], + "0x4200000000000000000000000000000000000019": [ + 1, + 0 + ], + "0x420000000000000000000000000000000000001a": [ + 0, + 2 + ], + "0x420000000000000000000000000000000000001b": [ + 1, + 1 + ] } } } \ No newline at end of file diff --git a/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json index 60cff1e58f..b0b0756576 100644 --- a/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json +++ b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json @@ -39,107 +39,143 @@ } }, { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 2 - }, - "0x000000000000000000000000000000000000ffff": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched", + "storage": {}, + "transaction_id": 2 + }, + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x61ffffff00", - "jump_table": { - "bits": 5, - "data": [ - 0 - ], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting | Cold", + "storage": {}, + "transaction_id": 2 + }, + "0x0000000000000000000000000000000000000000" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x61ffffff00", + "jump_table": { + "bits": 5, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 5 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0x9125466aa9ef15459d85e7318f6d3bdc5f6978c0565bee37a8e768d7c202a67a", + "nonce": 1 }, - "original_len": 5 - } - }, - "code_hash": "0x9125466aa9ef15459d85e7318f6d3bdc5f6978c0565bee37a8e768d7c202a67a", - "nonce": 1 - }, - "status": "Created | CreatedLocal | SelfDestructed | Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 2 - }, - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { - "info": { - "balance": "0x2386f26fc10000", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Created | CreatedLocal | SelfDestructed | Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 2 + }, + "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2" + ] + ], + [ + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched", - "storage": {}, - "transaction_id": 2 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 1 + }, + "0x000000000000000000000000000000000000ffff" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 1 + ], + "0x000000000000000000000000000000000000ffff": [ + 1, + 0 + ], + "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2": [ + 0, + 2 + ], + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + 0, + 0 + ] } } ] \ No newline at end of file diff --git a/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json index ccc0fe6dd4..be447c8c23 100644 --- a/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json +++ b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json @@ -22,105 +22,141 @@ } }, { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "accounts": [ + [ + [ + { + "info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 2 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 1 - }, - "0x000000000000000000000000000000000000ffff": { - "info": { - "balance": "0x2386f26fc10000", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched", + "storage": {}, + "transaction_id": 1 + }, + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { - "info": { - "balance": "0x2386f26fc10000", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "SelfDestructed | Touched", + "storage": {}, + "transaction_id": 1 + }, + "0xffffffffffffffffffffffffffffffffffffffff" + ], + [ + { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 2 - }, - "status": "Touched", - "storage": {}, - "transaction_id": 1 - }, - "0xffffffffffffffffffffffffffffffffffffffff": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 + "status": "Touched | LoadedAsNotExisting | Cold", + "storage": {}, + "transaction_id": 1 + }, + "0x0000000000000000000000000000000000000000" + ] + ], + [ + [ + { + "info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } }, - "order": "bitvec::order::Lsb0" + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "SelfDestructed | Touched", - "storage": {}, - "transaction_id": 1 + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x000000000000000000000000000000000000ffff" + ] + ] + ], + "index": { + "0x0000000000000000000000000000000000000000": [ + 0, + 2 + ], + "0x000000000000000000000000000000000000ffff": [ + 1, + 0 + ], + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": [ + 0, + 0 + ], + "0xffffffffffffffffffffffffffffffffffffffff": [ + 0, + 1 + ] } } ] \ No newline at end of file diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 043bb2eaaf..dc644d7ff7 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -12,7 +12,7 @@ use context_interface::{ }; use interpreter::interpreter_action::FrameInit; use interpreter::{Gas, InitialAndFloorGas, SharedMemory}; -use primitives::U256; +use primitives::{AddressAndId, TxKind, U256}; /// Trait for errors that can occur during EVM execution. /// @@ -123,6 +123,19 @@ pub trait Handler { ) -> Result, Self::Error> { // dummy values that are not used. let init_and_floor_gas = InitialAndFloorGas::new(0, 0); + // load caller and target + let (tx, journal) = evm.ctx().tx_journal_mut(); + // set dummy caller id as it is not used in system call. + journal.set_caller_address_id(AddressAndId::new(tx.caller(), (0, 0))); + + if let TxKind::Call(to) = tx.kind() { + let account_load = journal.load_account_delegated(to.into())?.data; + evm.ctx().journal_mut().set_tx_target_address_id( + account_load.address_and_id, + account_load.delegated_account_address.map(|d| d.data), + ); + } + // call execution and than output. match self .execution(evm, &init_and_floor_gas) @@ -175,9 +188,10 @@ pub trait Handler { #[inline] fn pre_execution(&self, evm: &mut Self::Evm) -> Result { self.validate_against_state_and_deduct_caller(evm)?; + let gas = self.apply_eip7702_auth_list(evm)?; + self.load_accounts(evm)?; - let gas = self.apply_eip7702_auth_list(evm)?; Ok(gas) } diff --git a/crates/inspector/src/count_inspector.rs b/crates/inspector/src/count_inspector.rs index a80d09af62..c2d3f01be4 100644 --- a/crates/inspector/src/count_inspector.rs +++ b/crates/inspector/src/count_inspector.rs @@ -5,6 +5,7 @@ use primitives::HashMap; /// Inspector that counts all opcodes that were called during execution. #[derive(Clone, Debug, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CountInspector { /// Map from opcode value to count of times it was executed. opcode_counts: HashMap, diff --git a/crates/inspector/src/gas.rs b/crates/inspector/src/gas.rs index 732679b0b6..e4b28cbe65 100644 --- a/crates/inspector/src/gas.rs +++ b/crates/inspector/src/gas.rs @@ -4,6 +4,7 @@ use interpreter::{CallOutcome, CreateOutcome, Gas}; /// Helper that keeps track of gas. #[allow(dead_code)] #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GasInspector { gas_remaining: u64, last_gas_cost: u64, diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index 6920f33b6c..0fed7dea7d 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -7,6 +7,7 @@ use interpreter::{ FrameInput, Host, InitialAndFloorGas, InstructionResult, Interpreter, InterpreterAction, InterpreterTypes, }; +use primitives::{AddressAndId, TxKind}; use state::bytecode::opcode; /// Trait that extends [`Handler`] with inspection functionality. @@ -136,6 +137,21 @@ where ) -> Result, Self::Error> { // dummy values that are not used. let init_and_floor_gas = InitialAndFloorGas::new(0, 0); + + let (tx, journal) = evm.ctx().tx_journal_mut(); + + // set dummy caller id as it is not used in system call. + journal.set_caller_address_id(AddressAndId::new(tx.caller(), (0, 0))); + + // load target + if let TxKind::Call(to) = tx.kind() { + let account_load = journal.load_account_delegated(to.into())?.data; + evm.ctx().journal_mut().set_tx_target_address_id( + account_load.address_and_id, + account_load.delegated_account_address.map(|d| d.data), + ); + } + // call execution with inspection and then output. match self .inspect_execution(evm, &init_and_floor_gas) diff --git a/crates/inspector/src/noop.rs b/crates/inspector/src/noop.rs index 09a97804ec..59d907b73f 100644 --- a/crates/inspector/src/noop.rs +++ b/crates/inspector/src/noop.rs @@ -3,6 +3,7 @@ use interpreter::InterpreterTypes; /// Dummy [Inspector], helpful as standalone replacement. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct NoOpInspector; impl Inspector for NoOpInspector {} diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 05332b2644..a93489db46 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -210,6 +210,9 @@ where caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } + // set caller id + journal.set_caller_address_id(caller_id); + // NOTE: all changes to the caller account should journaled so in case of error // we can revert the changes. journal.caller_accounting_journal_entry( @@ -1097,7 +1100,15 @@ mod tests { }, 0..0, )); - + handler.load_accounts(&mut evm).unwrap(); + // load caller account and id + let (_, caller_id) = evm + .ctx() + .journal_mut() + .load_account_code(SENDER.into()) + .unwrap() + .data; + evm.ctx().journal_mut().set_caller_address_id(caller_id); // Reimburse the caller for the unspent portion of the fees. handler .reimburse_caller(&mut evm, &mut exec_result) diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index ad666251f9..aa021b2623 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -11,7 +11,7 @@ pub type TransientStorage = HashMap<(AccountId, StorageKey), StorageValue>; pub type EvmStorage = HashMap; /// First page size is 3 to account for Caller, Target, and Beneficiary. -const FIRST_PAGE_SIZE: usize = 10; +const FIRST_PAGE_SIZE: usize = 3; /// Page size is 100. const PAGE_SIZE: usize = 100; @@ -54,11 +54,11 @@ impl EvmState { /// Take accounts. #[inline] pub fn take(&mut self) -> (AccountPages, HashMap) { - let accounts = std::mem::replace( + let accounts = core::mem::replace( &mut self.accounts, vec![Vec::with_capacity(FIRST_PAGE_SIZE)], ); - let index = std::mem::take(&mut self.index); + let index = core::mem::take(&mut self.index); (accounts, index) } @@ -421,7 +421,7 @@ mod tests { // Verify pagination structure assert!(state.accounts.len() >= 2); // Should have at least 2 pages - assert_eq!(state.accounts[0].len(), 100); // First page should be full + assert_eq!(state.accounts[0].len(), 3); // First page should be full } #[test] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/temp.json b/temp.json new file mode 100644 index 0000000000..bf5cfaf808 --- /dev/null +++ b/temp.json @@ -0,0 +1,118 @@ +{ + "tests/shanghai/eip3855_push0/test_push0.py::TestPush0CallContext::test_push0_contract_during_call_contexts[fork_Cancun-state_test-callcode]": { + "env": { + "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentGasLimit": "0x016345785d8a0000", + "currentNumber": "0x01", + "currentTimestamp": "0x03e8", + "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000", + "currentDifficulty": "0x00", + "currentBaseFee": "0x07", + "currentExcessBlobGas": "0x00" + }, + "pre": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0x3635c9adc5dea00000", + "code": "0x", + "storage": {} + }, + "0x0000000000000000000000000000000000001000": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60ff5f5360015ff3", + "storage": {} + }, + "0x0000000000000000000000000000000000001100": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60006000600060006000611000620186a0f2600055600160005560016000601f3e600051600155", + "storage": {} + } + }, + "transaction": { + "nonce": "0x00", + "gasPrice": "0x0a", + "gasLimit": [ + "0x0186a0" + ], + "to": "0x0000000000000000000000000000000000001100", + "value": [ + "0x00" + ], + "data": [ + "0x" + ], + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + }, + "post": { + "Cancun": [ + { + "hash": "0xad0c7fbb18e34ca1e08ca4d052102270cba4dc9f0c31c88994586d5bac4e8126", + "logs": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "txbytes": "0xf860800a830186a0940000000000000000000000000000000000001100808025a0450bb2501f58d443b494932d42891374385d2fef15af0090bf88adff0d247d6aa001f23877ce28d6d6986111de1b5594156a77690f214a2beba16f7556d3bf7a51", + "indexes": { + "data": 0, + "gas": 0, + "value": 0 + }, + "state": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x01", + "balance": "0x3635c9adc5de95a0ce", + "code": "0x", + "storage": {} + }, + "0x0000000000000000000000000000000000001000": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60ff5f5360015ff3", + "storage": {} + }, + "0x0000000000000000000000000000000000001100": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60006000600060006000611000620186a0f2600055600160005560016000601f3e600051600155", + "storage": { + "0x00": "0x01", + "0x01": "0xff" + } + }, + "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { + "nonce": "0x00", + "balance": "0x031c8f", + "code": "0x", + "storage": {} + } + } + } + ] + }, + "config": { + "blobSchedule": { + "Cancun": { + "target": "0x03", + "max": "0x06", + "baseFeeUpdateFraction": "0x32f0ed" + } + }, + "chainid": "0x01" + }, + "_info": { + "hash": "0x4041dff4f205819452f6d010b7839a4f9f9919d4e47cba3231bc1babfb1e8383", + "comment": "`execution-spec-tests` generated test", + "filling-transition-tool": "ethereum-spec-evm-resolver 0.0.5", + "description": "Test class documentation:\n\n Tests the PUSH0 operation during various call contexts including:\n - CALL\n - CALLCODE\n - DELEGATECALL\n - STATICCALL.\n \n\nTest PUSH0 during various call contexts.", + "url": "https://github.com/ethereum/execution-spec-tests/tree/v4.4.0/tests/shanghai/eip3855_push0/test_push0.py#L123", + "fixture-format": "state_test", + "reference-spec": "https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3855.md", + "reference-spec-version": "42034250ae8dd4b21fdc6795773893c6f1e74d3a", + "eels-resolution": { + "git-url": "https://github.com/ethereum/execution-specs.git", + "branch": "master", + "commit": "fa847a0e48309debee8edc510ceddb2fd5db2f2e" + } + } + } +} \ No newline at end of file From 49428ed264d3c6b2fb801ae417c9d0745b37b802 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 13:50:10 +0200 Subject: [PATCH 32/37] typo --- crates/interpreter/src/instructions/utility.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/instructions/utility.rs b/crates/interpreter/src/instructions/utility.rs index 20e6109377..f0148b2e10 100644 --- a/crates/interpreter/src/instructions/utility.rs +++ b/crates/interpreter/src/instructions/utility.rs @@ -18,7 +18,7 @@ impl IntoU256 for B256 { } } -/// Trait for converting types into Address values. It ingnores excess bytes. +/// Trait for converting types into Address values. It ignores excess bytes. pub trait IntoAddress { /// Converts the implementing type into an Address value. fn into_address(self) -> Address; From 574e8db7698765673d1ddf840bb17f96050a1461 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 17:37:53 +0200 Subject: [PATCH 33/37] fix problems --- .../context/interface/src/journaled_state.rs | 7 + crates/context/src/journal/inner.rs | 17 +- crates/handler/src/execution.rs | 12 +- crates/handler/src/frame.rs | 83 ++------ crates/handler/src/handler.rs | 5 +- crates/handler/src/pre_execution.rs | 10 +- .../interpreter/src/instructions/contract.rs | 8 + .../src/interpreter_action/call_inputs.rs | 2 + crates/state/src/types.rs | 2 +- temp.json | 187 ++++++++---------- 10 files changed, 148 insertions(+), 185 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index bfa1a738c1..4822bd5f59 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -317,6 +317,7 @@ impl AccountLoad { /// /// If the account has a delegated account, it returns the delegated account address. /// Otherwise, it returns the account address. + #[inline] pub fn bytecode_address(&self) -> AddressAndId { if let Some(delegated_account_address) = &self.delegated_account_address { delegated_account_address.data @@ -324,4 +325,10 @@ impl AccountLoad { self.address_and_id } } + + /// Returns whether the account is delegated. + #[inline] + pub fn is_delegated(&self) -> bool { + self.delegated_account_address.is_some() + } } diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index eb21f7dd84..a8ddde2b20 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -610,7 +610,7 @@ impl JournalInner { ) -> Result, DB::Error> { let spec = self.spec; let is_eip7702_enabled = spec.is_enabled_in(SpecId::PRAGUE); - let account = self.load_account_optional(db, address_or_id, is_eip7702_enabled, [])?; + let account = self.load_account_optional(db, address_or_id, true, [])?; let is_empty = account.0.state_clear_aware_is_empty(spec); let mut account_load = StateLoad::new( @@ -623,11 +623,14 @@ impl JournalInner { ); // load delegate code if account is EIP-7702 - if let Some(Bytecode::Eip7702(code)) = &account.0.info.code { - let address = code.address(); - let delegate_account = self.load_account(db, AddressOrId::Address(address))?; - account_load.data.delegated_account_address = - Some(StateLoad::new(delegate_account.1, delegate_account.is_cold)); + if is_eip7702_enabled { + if let Some(Bytecode::Eip7702(code)) = &account.0.info.code { + let address = code.address(); + let delegate_account = + self.load_account_optional(db, AddressOrId::Address(address), true, [])?; + account_load.data.delegated_account_address = + Some(StateLoad::new(delegate_account.1, delegate_account.is_cold)); + } } Ok(account_load) @@ -667,7 +670,7 @@ impl JournalInner { } else { Account::new_not_existing(self.transaction_id) }; - account.status |= AccountStatus::Cold; + account.status.insert(AccountStatus::Cold); account }) })? diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index f769cc80f1..6c5e95c418 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -13,16 +13,18 @@ pub fn create_init_frame( gas_limit: u64, ) -> FrameInput { if let Some((target, delegated_address)) = target { - let bytecode_address = if let Some(delegated_address) = delegated_address { - delegated_address - } else { - target - }; + let (bytecode_address, is_bytecode_delegated) = + if let Some(delegated_address) = delegated_address { + (delegated_address, true) + } else { + (target, false) + }; FrameInput::Call(Box::new(CallInputs { input: CallInput::Bytes(input), gas_limit, target_address: target, bytecode_address, + is_bytecode_delegated, caller, value: CallValue::Transfer(value), scheme: CallScheme::Call, diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 7b27d7ca22..67063e803b 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -187,26 +187,28 @@ impl EthFrame { }; let is_static = inputs.is_static; let gas_limit = inputs.gas_limit; - - if let Some(result) = precompiles - .run( - ctx, - inputs.bytecode_address.address(), - &interpreter_input, - is_static, - gas_limit, - ) - .map_err(ERROR::from_string)? - { - if result.result.is_ok() { - ctx.journal_mut().checkpoint_commit(); - } else { - ctx.journal_mut().checkpoint_revert(checkpoint); + // if account is delegate, we skip precompile address check. + if !inputs.is_bytecode_delegated { + if let Some(result) = precompiles + .run( + ctx, + inputs.bytecode_address.address(), + &interpreter_input, + is_static, + gas_limit, + ) + .map_err(ERROR::from_string)? + { + if result.result.is_ok() { + ctx.journal_mut().checkpoint_commit(); + } else { + ctx.journal_mut().checkpoint_revert(checkpoint); + } + return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { + result, + memory_offset: inputs.return_memory_offset.clone(), + }))); } - return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { - result, - memory_offset: inputs.return_memory_offset.clone(), - }))); } let (bytecode_account, _) = ctx.journal_mut().get_account(inputs.bytecode_address.id()); @@ -237,49 +239,6 @@ impl EthFrame { Ok(ItemOrResult::Item(this.consume())) } - /* - - - instruction CALL: - I want to set all fields that interpreter is going to use? - // Should i used InputsImpl, probably yes? - - Additionally i needs some specific data for Call info - - Call specific are: - return_memory_offset - scheme - is_static - - Create specific: - Scheme - init_code can be data - - CallInput: - InputsImpl - - - FrameInput: - Interpreter `Inputs for FrameInput` - - FrameOutput: - InterpResult - scheme: - return_mem: - address: - - - CreateInput: - InputsImpl: - - - What do I want? - To consolidate Inputs and CallInput CreateInput. - - - - */ - /// Make create frame. #[inline] pub fn make_create_frame< diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index dc644d7ff7..2ff3ddce37 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -188,11 +188,8 @@ pub trait Handler { #[inline] fn pre_execution(&self, evm: &mut Self::Evm) -> Result { self.validate_against_state_and_deduct_caller(evm)?; - let gas = self.apply_eip7702_auth_list(evm)?; - self.load_accounts(evm)?; - - Ok(gas) + self.apply_eip7702_auth_list(evm) } /// Creates and executes the initial frame, then processes the execution loop. diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index a4eabd56d6..a050167a0d 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -55,14 +55,18 @@ pub fn load_accounts< ); } - let (coinbase, id) = journal.load_account_code(beneficiary)?.data; + let mut coinbase = journal.load_account(beneficiary)?; // Load coinbase // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm if spec.is_enabled_in(SpecId::SHANGHAI) { - coinbase.mark_touch(); + coinbase.0.mark_touch(); } else { - coinbase.mark_cold(); + // if coinbase was cold mark it cold again. If it was warm it can mean that it was added as part of access list. + if coinbase.is_cold { + coinbase.0.mark_cold(); + } } + let id = coinbase.1; journal.set_coinbase_address_id(id); let (context, precompiles) = evm.ctx_precompiles(); diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index ae6d5e11c5..8c09e3a96a 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -135,6 +135,7 @@ pub fn call(context: InstructionContex }; let to = account_load.address_and_id; let bytecode_address = account_load.bytecode_address(); + let is_bytecode_delegated = account_load.is_delegated(); let Some(mut gas_limit) = calc_call_gas( context.interpreter, @@ -163,6 +164,7 @@ pub fn call(context: InstructionContex target_address: to, caller: context.interpreter.input.target_address(), bytecode_address, + is_bytecode_delegated, value: CallValue::Transfer(value), scheme: CallScheme::Call, is_static: context.interpreter.runtime_flag.is_static(), @@ -195,6 +197,7 @@ pub fn call_code( return; }; let bytecode_address = load.bytecode_address(); + let is_bytecode_delegated = load.is_delegated(); // Set `is_empty` to false as we are not creating this account. load.is_empty = false; @@ -222,6 +225,7 @@ pub fn call_code( target_address: context.interpreter.input.target_address(), caller: context.interpreter.input.target_address(), bytecode_address, + is_bytecode_delegated, value: CallValue::Transfer(value), scheme: CallScheme::CallCode, is_static: context.interpreter.runtime_flag.is_static(), @@ -254,6 +258,7 @@ pub fn delegate_call( return; }; let bytecode_address = load.bytecode_address(); + let is_bytecode_delegated = load.is_delegated(); // Set is_empty to false as we are not creating this account. load.is_empty = false; @@ -274,6 +279,7 @@ pub fn delegate_call( target_address: context.interpreter.input.target_address(), caller: context.interpreter.input.caller_address(), bytecode_address, + is_bytecode_delegated, value: CallValue::Apparent(context.interpreter.input.call_value()), scheme: CallScheme::DelegateCall, is_static: context.interpreter.runtime_flag.is_static(), @@ -307,6 +313,7 @@ pub fn static_call( }; let to = load.address_and_id; let bytecode_address = load.bytecode_address(); + let is_bytecode_delegated = load.is_delegated(); // Set `is_empty` to false as we are not creating this account. load.is_empty = false; @@ -326,6 +333,7 @@ pub fn static_call( target_address: to, caller: context.interpreter.input.target_address(), bytecode_address, + is_bytecode_delegated, value: CallValue::Transfer(U256::ZERO), scheme: CallScheme::StaticCall, is_static: true, diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index eaff6c02e3..66d8ac900a 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -78,6 +78,8 @@ pub struct CallInputs { /// /// Previously `context.code_address`. pub bytecode_address: AddressAndId, + /// Whether the bytecode address is a delegated address. In this case precompile check will be skipped. + pub is_bytecode_delegated: bool, /// Target address, this account storage is going to be modified. /// /// Previously `context.address`. diff --git a/crates/state/src/types.rs b/crates/state/src/types.rs index aa021b2623..75028daa9d 100644 --- a/crates/state/src/types.rs +++ b/crates/state/src/types.rs @@ -515,7 +515,7 @@ mod tests { // Verify all addresses are present for (account, address) in collected { - assert!(expected_addresses.contains(&address)); + assert!(expected_addresses.contains(address)); let index = expected_addresses .iter() .position(|&a| a == *address) diff --git a/temp.json b/temp.json index bf5cfaf808..d6295cd939 100644 --- a/temp.json +++ b/temp.json @@ -1,118 +1,99 @@ { - "tests/shanghai/eip3855_push0/test_push0.py::TestPush0CallContext::test_push0_contract_during_call_contexts[fork_Cancun-state_test-callcode]": { - "env": { - "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentGasLimit": "0x016345785d8a0000", - "currentNumber": "0x01", - "currentTimestamp": "0x03e8", - "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000", - "currentDifficulty": "0x00", - "currentBaseFee": "0x07", - "currentExcessBlobGas": "0x00" - }, - "pre": { - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x00", - "balance": "0x3635c9adc5dea00000", - "code": "0x", - "storage": {} - }, - "0x0000000000000000000000000000000000001000": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x60ff5f5360015ff3", - "storage": {} + "coinbaseT2" : { + "_info" : { + "comment" : "Ori Pomerantz qbzzt1@gmail.com", + "filling-rpc-server" : "evm version 1.13.11-unstable-765f2904-20240124", + "filling-tool-version" : "retesteth-0.3.2-cancun+commit.ea13235b.Linux.g++", + "generatedTestHash" : "285574ee1ad31ad4856775100de9af261ad0a18f7e1bd569ed68b037ab0a233e", + "labels" : { + "0" : "T2baseInList", + "1" : "T2baseNotInList" }, - "0x0000000000000000000000000000000000001100": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x60006000600060006000611000620186a0f2600055600160005560016000601f3e600051600155", - "storage": {} - } + "lllcversion" : "Version: 0.5.14-develop.2023.7.11+commit.c58ab2c6.mod.Linux.g++", + "solidity" : "Version: 0.8.21+commit.d9974bed.Linux.g++", + "source" : "src/GeneralStateTestsFiller/stEIP2930/coinbaseT2Filler.yml", + "sourceHash" : "9814046d78a2de187ef8f9acd8e9ec7018c69e3960896642083502368e56fd04" }, - "transaction": { - "nonce": "0x00", - "gasPrice": "0x0a", - "gasLimit": [ - "0x0186a0" - ], - "to": "0x0000000000000000000000000000000000001100", - "value": [ - "0x00" - ], - "data": [ - "0x" - ], - "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + "env" : { + "currentBaseFee" : "0x64", + "currentCoinbase" : "0x000000000000000000000000000000000000ba5e", + "currentDifficulty" : "0x020000", + "currentExcessBlobGas" : "0x00", + "currentGasLimit" : "0xff112233445566", + "currentNumber" : "0x01", + "currentRandom" : "0x0000000000000000000000000000000000000000000000000000000000020000", + "currentTimestamp" : "0x03e8" }, - "post": { - "Cancun": [ + "post" : { + "London" : [ { - "hash": "0xad0c7fbb18e34ca1e08ca4d052102270cba4dc9f0c31c88994586d5bac4e8126", - "logs": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "txbytes": "0xf860800a830186a0940000000000000000000000000000000000001100808025a0450bb2501f58d443b494932d42891374385d2fef15af0090bf88adff0d247d6aa001f23877ce28d6d6986111de1b5594156a77690f214a2beba16f7556d3bf7a51", - "indexes": { - "data": 0, - "gas": 0, - "value": 0 + "hash" : "0xb4d2b8ad5073b84c87fe77459cd658509c741af303d19cba52663cd35b076aec", + "indexes" : { + "data" : 0, + "gas" : 0, + "value" : 0 }, - "state": { - "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "nonce": "0x01", - "balance": "0x3635c9adc5de95a0ce", - "code": "0x", - "storage": {} - }, - "0x0000000000000000000000000000000000001000": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x60ff5f5360015ff3", - "storage": {} - }, - "0x0000000000000000000000000000000000001100": { - "nonce": "0x01", - "balance": "0x00", - "code": "0x60006000600060006000611000620186a0f2600055600160005560016000601f3e600051600155", - "storage": { - "0x00": "0x01", - "0x01": "0xff" - } - }, - "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { - "nonce": "0x00", - "balance": "0x031c8f", - "code": "0x", - "storage": {} - } - } + "logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "txbytes" : "0x02f8a10101648227108402625a0094000000000000000000000000000000000000c0de80a4693c61390000000000000000000000000000000000000000000000000000000000000000d7d694000000000000000000000000000000000000ba5ec080a0d5a3052a8cc387f35ffdebe832afdfdd45980cdcbb9b926dee7fb9b1d9a4ee08a06210d404eb6aecd05bc214b120959a71ede9fadcae4b769c96c58bffa216f205" } ] }, - "config": { - "blobSchedule": { - "Cancun": { - "target": "0x03", - "max": "0x06", - "baseFeeUpdateFraction": "0x32f0ed" + "pre" : { + "0x000000000000000000000000000000000000ba5e" : { + "balance" : "0x00", + "code" : "0x", + "nonce" : "0x01", + "storage" : { } }, - "chainid": "0x01" - }, - "_info": { - "hash": "0x4041dff4f205819452f6d010b7839a4f9f9919d4e47cba3231bc1babfb1e8383", - "comment": "`execution-spec-tests` generated test", - "filling-transition-tool": "ethereum-spec-evm-resolver 0.0.5", - "description": "Test class documentation:\n\n Tests the PUSH0 operation during various call contexts including:\n - CALL\n - CALLCODE\n - DELEGATECALL\n - STATICCALL.\n \n\nTest PUSH0 during various call contexts.", - "url": "https://github.com/ethereum/execution-spec-tests/tree/v4.4.0/tests/shanghai/eip3855_push0/test_push0.py#L123", - "fixture-format": "state_test", - "reference-spec": "https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3855.md", - "reference-spec-version": "42034250ae8dd4b21fdc6795773893c6f1e74d3a", - "eels-resolution": { - "git-url": "https://github.com/ethereum/execution-specs.git", - "branch": "master", - "commit": "fa847a0e48309debee8edc510ceddb2fd5db2f2e" + "0x000000000000000000000000000000000000c0de" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x5a6000526000808080620f424061ba5e5af1505a6020526021602051600051030360005500", + "nonce" : "0x01", + "storage" : { + } + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x", + "nonce" : "0x01", + "storage" : { + } } + }, + "transaction" : { + "accessLists" : [ + [ + { + "address" : "0x000000000000000000000000000000000000ba5e", + "storageKeys" : [ + ] + } + ], + [ + { + "address" : "0x000000000000000000000000000000000000ba5a", + "storageKeys" : [ + ] + } + ] + ], + "data" : [ + "0x693c61390000000000000000000000000000000000000000000000000000000000000000", + "0x693c61390000000000000000000000000000000000000000000000000000000000000000" + ], + "gasLimit" : [ + "0x02625a00" + ], + "maxFeePerGas" : "0x2710", + "maxPriorityFeePerGas" : "0x64", + "nonce" : "0x01", + "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "sender" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "to" : "0x000000000000000000000000000000000000c0de", + "value" : [ + "0x00" + ] } } } \ No newline at end of file From b6ddff648bad1cc6016d9cc9ab3ed532ecc72c2e Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 18:57:47 +0200 Subject: [PATCH 34/37] extcodehash does not need to load code --- crates/context/interface/src/journaled_state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 4822bd5f59..359dd77f84 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -187,7 +187,7 @@ pub trait JournalTr { &mut self, address_or_id: AddressOrId, ) -> Result<(StateLoad, AddressAndId), ::Error> { - let acc = self.load_account_code(address_or_id)?; + let acc = self.load_account(address_or_id)?; if acc.0.is_empty() { return Ok((StateLoad::new(B256::ZERO, acc.is_cold), acc.1)); } From c7e7ca13fd87c5b3fb4e1114d5e443a30abee984 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 20:00:18 +0200 Subject: [PATCH 35/37] fix eip7702 --- crates/handler/src/handler.rs | 7 ++++++- crates/handler/src/mainnet_builder.rs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 2ff3ddce37..7fce3e6ef5 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -187,9 +187,14 @@ pub trait Handler { /// Returns the gas refund amount from EIP-7702. Authorizations are applied before execution begins. #[inline] fn pre_execution(&self, evm: &mut Self::Evm) -> Result { + // nonce gets updated self.validate_against_state_and_deduct_caller(evm)?; + // nonces of authneticators got updated + let eip7702_refund = self.apply_eip7702_auth_list(evm)?; + // target/beneficiary accounts got loaded with access list. self.load_accounts(evm)?; - self.apply_eip7702_auth_list(evm) + + Ok(eip7702_refund) } /// Creates and executes the initial frame, then processes the execution loop. diff --git a/crates/handler/src/mainnet_builder.rs b/crates/handler/src/mainnet_builder.rs index 85a35b2a2f..d570789992 100644 --- a/crates/handler/src/mainnet_builder.rs +++ b/crates/handler/src/mainnet_builder.rs @@ -119,6 +119,7 @@ mod test { .unwrap() .state; + println!("state: {:#?}", state); let auth_acc = state.get(signer.address().into()).unwrap(); assert_eq!(auth_acc.0.info.code, Some(Bytecode::new_eip7702(FFADDRESS))); assert_eq!(auth_acc.0.info.nonce, 1); From 4c03a04394f1d1c02921ff467a18235d7e44cccd Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 20:25:29 +0200 Subject: [PATCH 36/37] skip loading caller account in create --- crates/handler/src/frame.rs | 2 +- crates/interpreter/src/interpreter_action/create_outcome.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 67063e803b..254d45e1e3 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -271,7 +271,7 @@ impl EthFrame { // Fetch balance of caller. let caller_info = &mut context .journal_mut() - .load_account(inputs.caller.to_id())? + .get_account_mut(inputs.caller.id()) .0 .info; diff --git a/crates/interpreter/src/interpreter_action/create_outcome.rs b/crates/interpreter/src/interpreter_action/create_outcome.rs index b54f3aca5b..dc2da676bc 100644 --- a/crates/interpreter/src/interpreter_action/create_outcome.rs +++ b/crates/interpreter/src/interpreter_action/create_outcome.rs @@ -21,7 +21,7 @@ impl CreateOutcome { /// # Arguments /// /// * `result` - An [`InterpreterResult`] representing the result of the interpreter operation. - /// * `address` - An optional [`Address`] associated with the create operation. + /// * `AddressAndId` - An optional [`AddressAndId`] associated with the create operation. /// /// # Returns /// From eeb693845a6ce77afc399a430d11ea3fe86c2748 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 14 Aug 2025 20:44:03 +0200 Subject: [PATCH 37/37] inline host functions --- crates/context/src/context.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index e645ef11e5..468ee5e42d 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -456,53 +456,65 @@ impl< { /* Block */ + #[inline] fn basefee(&self) -> U256 { U256::from(self.block().basefee()) } + #[inline] fn blob_gasprice(&self) -> U256 { U256::from(self.block().blob_gasprice().unwrap_or(0)) } + #[inline] fn gas_limit(&self) -> U256 { U256::from(self.block().gas_limit()) } + #[inline] fn difficulty(&self) -> U256 { self.block().difficulty() } + #[inline] fn prevrandao(&self) -> Option { self.block().prevrandao().map(|r| r.into()) } + #[inline] fn block_number(&self) -> U256 { self.block().number() } + #[inline] fn timestamp(&self) -> U256 { U256::from(self.block().timestamp()) } + #[inline] fn beneficiary(&self) -> Address { self.block().beneficiary() } + #[inline] fn chain_id(&self) -> U256 { U256::from(self.cfg().chain_id()) } /* Transaction */ + #[inline] fn effective_gas_price(&self) -> U256 { let basefee = self.block().basefee(); U256::from(self.tx().effective_gas_price(basefee as u128)) } + #[inline] fn caller(&self) -> Address { self.tx().caller() } + #[inline] fn blob_hash(&self, number: usize) -> Option { let tx = &self.tx(); if tx.tx_type() != TransactionType::Eip4844 { @@ -515,12 +527,14 @@ impl< /* Config */ + #[inline] fn max_initcode_size(&self) -> usize { self.cfg().max_initcode_size() } /* Database */ + #[inline] fn block_hash(&mut self, requested_number: u64) -> Option { self.db_mut() .block_hash(requested_number) @@ -532,6 +546,8 @@ impl< /* Journal */ + /// Load account and its delegated account if EIP-7702 is enabled. + #[inline] fn load_account_delegated( &mut self, address_or_id: AddressOrId, @@ -545,6 +561,7 @@ impl< } /// Gets balance of `address` and if the account is cold. + #[inline] fn balance(&mut self, address_or_id: AddressOrId) -> Option> { self.journal_mut() .load_account(address_or_id) @@ -556,6 +573,7 @@ impl< } /// Gets code of `address` and if the account is cold. + #[inline] fn load_account_code(&mut self, address_or_id: AddressOrId) -> Option> { self.journal_mut() .code(address_or_id) @@ -567,6 +585,7 @@ impl< } /// Gets code hash of `address` and if the account is cold. + #[inline] fn load_account_code_hash(&mut self, address_or_id: AddressOrId) -> Option> { self.journal_mut() .code_hash(address_or_id) @@ -578,6 +597,7 @@ impl< } /// Gets storage value of `address` at `index` and if the account is cold. + #[inline] fn sload( &mut self, address: AddressOrId, @@ -594,6 +614,7 @@ impl< /// Sets storage value of account address at index. /// /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value. + #[inline] fn sstore( &mut self, address: AddressOrId, @@ -609,21 +630,25 @@ impl< } /// Gets the transient storage value of `address` at `index`. + #[inline] fn tload(&mut self, address: AddressOrId, index: StorageKey) -> StorageValue { self.journal_mut().tload(address, index) } /// Sets the transient storage value of `address` at `index`. + #[inline] fn tstore(&mut self, address: AddressOrId, index: StorageKey, value: StorageValue) { self.journal_mut().tstore(address, index, value) } /// Emits a log owned by `address` with given `LogData`. + #[inline] fn log(&mut self, log: Log) { self.journal_mut().log(log); } /// Marks `address` to be deleted, with funds transferred to `target`. + #[inline] fn selfdestruct( &mut self, address: AddressOrId,