diff --git a/Cargo.lock b/Cargo.lock index 5087985f71..de669e111d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,8 +77,11 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", + "arbitrary", "c-kzg", "once_cell", + "proptest", + "proptest-derive", "serde", "sha2", ] @@ -243,6 +246,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c224916316519558d8c2b6a60dc7626688c08f1b8951774702562dbcb8666ee" dependencies = [ "alloy-primitives", + "arbitrary", + "proptest", + "proptest-derive", "serde", "serde_json", ] @@ -385,6 +391,9 @@ name = "arbitrary" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "ark-ff" @@ -3144,6 +3153,7 @@ dependencies = [ name = "revm-primitives" version = "4.0.0" dependencies = [ + "alloy-eips", "alloy-primitives", "auto_impl", "bitflags 2.5.0", diff --git a/bins/revme/src/cmd/statetest/models/mod.rs b/bins/revme/src/cmd/statetest/models/mod.rs index 0225daaccc..ad409f016c 100644 --- a/bins/revme/src/cmd/statetest/models/mod.rs +++ b/bins/revme/src/cmd/statetest/models/mod.rs @@ -1,4 +1,4 @@ -use revm::primitives::{Address, Bytes, HashMap, B256, U256}; +use revm::primitives::{AccessList, Address, Bytes, HashMap, B256, U256}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -110,15 +110,6 @@ pub struct TransactionParts { pub max_fee_per_blob_gas: Option, } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct AccessListItem { - pub address: Address, - pub storage_keys: Vec, -} - -pub type AccessList = Vec; - #[cfg(test)] mod tests { diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 06ab1d64bd..48c62f35fe 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -10,7 +10,7 @@ use revm::{ inspectors::TracerEip3155, primitives::{ calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, Env, Eof, - ExecutionResult, SpecId, TxKind, B256, EOF_MAGIC_BYTES, U256, + ExecutionResult, SpecId, TxKind, B256, EOF_MAGIC_BYTES, }, Evm, State, }; @@ -350,18 +350,8 @@ pub fn execute_test_suite( .access_lists .get(test.indexes.data) .and_then(Option::as_deref) - .unwrap_or_default() - .iter() - .map(|item| { - ( - item.address, - item.storage_keys - .iter() - .map(|key| U256::from_be_bytes(key.0)) - .collect::>(), - ) - }) - .collect(); + .cloned() + .unwrap_or_default(); let to = match unit.transaction.to { Some(add) => TxKind::Call(add), diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index dd434fcd27..0c4ca2481a 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,10 +1,11 @@ +use revm_primitives::AccessListItem; + use super::constants::*; use crate::{ num_words, - primitives::{Address, SpecId, U256}, + primitives::{SpecId, U256}, SelfDestructResult, }; -use std::vec::Vec; /// `const` Option `?`. macro_rules! tri { @@ -357,7 +358,7 @@ pub fn validate_initial_tx_gas( spec_id: SpecId, input: &[u8], is_create: bool, - access_list: &[(Address, Vec)], + access_list: &[AccessListItem], ) -> u64 { let mut initial_gas = 0; let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; @@ -375,11 +376,12 @@ pub fn validate_initial_tx_gas( // get number of access list account and storages. if spec_id.is_enabled_in(SpecId::BERLIN) { - let accessed_slots = access_list + let accessed_slots: usize = access_list .iter() - .fold(0, |slot_count, (_, slots)| slot_count + slots.len() as u64); + .map(|item| item.storage_keys.len()) + .sum(); initial_gas += access_list.len() as u64 * ACCESS_LIST_ADDRESS; - initial_gas += accessed_slots * ACCESS_LIST_STORAGE_KEY; + initial_gas += accessed_slots as u64 * ACCESS_LIST_STORAGE_KEY; } // base stipend diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index a9d009d2e4..5041dc437e 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -22,6 +22,7 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] +alloy-eips = { version = "0.1", default-features = false } alloy-primitives = { version = "0.7.2", default-features = false, features = [ "rlp", ] } @@ -53,6 +54,7 @@ hex = { version = "0.4", default-features = false } default = ["std", "c-kzg", "portable"] std = [ "serde?/std", + "alloy-eips/std", "alloy-primitives/std", "hex/std", "bitvec/std", @@ -61,6 +63,7 @@ std = [ hashbrown = [] serde = [ "dep:serde", + "alloy-eips/serde", "alloy-primitives/serde", "hex/serde", "hashbrown/serde", @@ -68,7 +71,12 @@ serde = [ "bitflags/serde", "c-kzg?/serde", ] -arbitrary = ["std", "alloy-primitives/arbitrary", "bitflags/arbitrary"] +arbitrary = [ + "std", + "alloy-eips/arbitrary", + "alloy-primitives/arbitrary", + "bitflags/arbitrary" +] asm-keccak = ["alloy-primitives/asm-keccak"] portable = ["c-kzg?/portable"] diff --git a/crates/primitives/src/bytecode/eof.rs b/crates/primitives/src/bytecode/eof.rs index db6814b793..c4d9377f59 100644 --- a/crates/primitives/src/bytecode/eof.rs +++ b/crates/primitives/src/bytecode/eof.rs @@ -215,8 +215,10 @@ mod test { assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]); assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]); assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]); - assert_eq!(eof.data_slice(10, 2), &[]); - assert_eq!(eof.data_slice(1, 0), &[]); - assert_eq!(eof.data_slice(10, 0), &[]); + + const EMPTY: &[u8] = &[]; + assert_eq!(eof.data_slice(10, 2), EMPTY); + assert_eq!(eof.data_slice(1, 0), EMPTY); + assert_eq!(eof.data_slice(10, 0), EMPTY); } } diff --git a/crates/primitives/src/bytecode/eof/header.rs b/crates/primitives/src/bytecode/eof/header.rs index 1074f066a4..a0990a6efe 100644 --- a/crates/primitives/src/bytecode/eof/header.rs +++ b/crates/primitives/src/bytecode/eof/header.rs @@ -242,7 +242,7 @@ mod tests { let (header, _) = EofHeader::decode(&input).unwrap(); assert_eq!(header.types_size, 4); assert_eq!(header.code_sizes, vec![1]); - assert_eq!(header.container_sizes, vec![]); + assert_eq!(header.container_sizes, Vec::::new()); assert_eq!(header.data_size, 0); } diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index fde04c5734..162aa0c130 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -4,9 +4,9 @@ use alloy_primitives::TxKind; pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg}; use crate::{ - calc_blob_gasprice, Account, Address, Bytes, InvalidHeader, InvalidTransaction, Spec, SpecId, - B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, - VERSIONED_HASH_VERSION_KZG, + calc_blob_gasprice, AccessListItem, Account, Address, Bytes, InvalidHeader, InvalidTransaction, + Spec, SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, + U256, VERSIONED_HASH_VERSION_KZG, }; use core::cmp::{min, Ordering}; use core::hash::Hash; @@ -526,7 +526,7 @@ pub struct TxEnv { /// Added in [EIP-2930]. /// /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 - pub access_list: Vec<(Address, Vec)>, + pub access_list: Vec, /// The priority fee per gas. /// @@ -704,7 +704,10 @@ mod tests { #[test] fn test_validate_tx_access_list() { let mut env = Env::default(); - env.tx.access_list = vec![(Address::ZERO, vec![])]; + env.tx.access_list = vec![AccessListItem { + address: Address::ZERO, + storage_keys: vec![], + }]; assert_eq!( env.validate_tx::(), Err(InvalidTransaction::AccessListNotSupported) diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 35019aa041..78e939d5f7 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -19,6 +19,7 @@ pub mod result; pub mod specification; pub mod state; pub mod utilities; +pub use alloy_eips::eip2930::{AccessList, AccessListItem}; pub use alloy_primitives::{ self, address, b256, bytes, fixed_bytes, hex, hex_literal, ruint, uint, Address, Bytes, FixedBytes, Log, LogData, TxKind, B256, I256, U256, diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index c83d5ec14a..aad9b73671 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -7,8 +7,8 @@ use crate::{ }, journaled_state::JournaledState, primitives::{ - keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env, - Eof, HashSet, Spec, + keccak256, AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, + EVMError, Env, Eof, HashSet, Spec, SpecId::{self, *}, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, @@ -100,9 +100,13 @@ impl InnerEvmContext { /// Loading of accounts/storages is needed to make them warm. #[inline] pub fn load_access_list(&mut self) -> Result<(), EVMError> { - for (address, slots) in self.env.tx.access_list.iter() { + for AccessListItem { + address, + storage_keys, + } in self.env.tx.access_list.iter() + { self.journaled_state - .initial_account_load(*address, slots, &mut self.db)?; + .initial_account_load(*address, storage_keys, &mut self.db)?; } Ok(()) } diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index 6ed29e8ba6..81ecc09f18 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -6,6 +6,7 @@ use crate::primitives::{ use core::mem; use revm_interpreter::primitives::SpecId; use revm_interpreter::{LoadAccountResult, SStoreResult}; +use revm_precompile::B256; use std::vec::Vec; /// JournalState is internal EVM state that is used to contain state and track changes to that state. @@ -530,7 +531,7 @@ impl JournaledState { pub fn initial_account_load( &mut self, address: Address, - slots: &[U256], + storage_keys: &[B256], db: &mut DB, ) -> Result<&mut Account, EVMError> { // load or get account. @@ -544,9 +545,10 @@ impl JournaledState { ), }; // preload storages. - for slot in slots { - if let Entry::Vacant(entry) = account.storage.entry(*slot) { - let storage = db.storage(address, *slot).map_err(EVMError::Database)?; + for storage_key in storage_keys { + let slot = U256::from_be_bytes(storage_key.0); + if let Entry::Vacant(entry) = account.storage.entry(slot) { + let storage = db.storage(address, slot).map_err(EVMError::Database)?; entry.insert(EvmStorageSlot::new(storage)); } } diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index 59d9d03680..c3cba6ffb3 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -6,7 +6,7 @@ use ethers_providers::{Http, Provider}; use indicatif::ProgressBar; use revm::db::{CacheDB, EthersDB, StateBuilder}; use revm::inspectors::TracerEip3155; -use revm::primitives::{Address, TxKind, U256}; +use revm::primitives::{AccessListItem, Address, TxKind, B256, U256}; use revm::{inspector_handle_register, Evm}; use std::fs::OpenOptions; use std::io::BufWriter; @@ -130,12 +130,16 @@ async fn main() -> anyhow::Result<()> { .0 .into_iter() .map(|item| { - let new_keys: Vec = item + let storage_keys: Vec = item .storage_keys .into_iter() - .map(|h256| U256::from_le_bytes(h256.0)) + .map(|h256| B256::new(h256.0)) .collect(); - (Address::from(item.address.as_fixed_bytes()), new_keys) + + AccessListItem { + address: Address::new(item.address.0), + storage_keys, + } }) .collect(); } else {