From f38aae6e8b8d28c9b74e1beb6e26465b6c3a3443 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 28 Nov 2024 18:10:19 +0100 Subject: [PATCH] remvme bench, builder for context --- bins/revme/src/cmd.rs | 25 ++-- bins/revme/src/cmd/bench/analysis.rs | 23 ++- bins/revme/src/cmd/bench/burntpix.rs | 25 ++-- bins/revme/src/cmd/bench/snailtracer.rs | 15 +- bins/revme/src/cmd/bench/transfer.rs | 15 +- bins/revme/src/cmd/evmrunner.rs | 3 +- bins/revme/src/cmd/statetest/runner.rs | 47 ++---- crates/context/src/context.rs | 185 +++++++++++++++++++++++- crates/context/src/journaled_state.rs | 8 +- crates/handler/src/lib.rs | 12 ++ crates/handler/src/validation.rs | 11 +- crates/revm/src/evm.rs | 10 ++ 12 files changed, 271 insertions(+), 108 deletions(-) diff --git a/bins/revme/src/cmd.rs b/bins/revme/src/cmd.rs index 1af1018c12..a31dca77f8 100644 --- a/bins/revme/src/cmd.rs +++ b/bins/revme/src/cmd.rs @@ -1,7 +1,7 @@ -// pub mod bench; +pub mod bench; pub mod bytecode; -// pub mod eofvalidation; -// pub mod evmrunner; +pub mod eofvalidation; +//pub mod evmrunner; pub mod statetest; use clap::Parser; @@ -12,14 +12,14 @@ use clap::Parser; pub enum MainCmd { /// Execute Ethereum state tests. Statetest(statetest::Cmd), - // /// Execute eof validation tests. - // EofValidation(eofvalidation::Cmd), + /// Execute eof validation tests. + EofValidation(eofvalidation::Cmd), // /// Run arbitrary EVM bytecode. // Evm(evmrunner::Cmd), /// Print the structure of an EVM bytecode. Bytecode(bytecode::Cmd), - // /// Run bench from specified list. - // Bench(bench::Cmd), + /// Run bench from specified list. + Bench(bench::Cmd), } #[derive(Debug, thiserror::Error)] @@ -41,15 +41,16 @@ impl MainCmd { pub fn run(&self) -> Result<(), Error> { match self { Self::Statetest(cmd) => cmd.run().map_err(Into::into), - // Self::EofValidation(cmd) => cmd.run().map_err(Into::into), + Self::EofValidation(cmd) => cmd.run().map_err(Into::into), // Self::Evm(cmd) => cmd.run().map_err(Into::into), Self::Bytecode(cmd) => { cmd.run(); Ok(()) - } // Self::Bench(cmd) => { - // cmd.run(); - // Ok(()) - // } + } + Self::Bench(cmd) => { + cmd.run(); + Ok(()) + } } } } diff --git a/bins/revme/src/cmd/bench/analysis.rs b/bins/revme/src/cmd/bench/analysis.rs index 8fc494f7d6..3c3df42f4a 100644 --- a/bins/revme/src/cmd/bench/analysis.rs +++ b/bins/revme/src/cmd/bench/analysis.rs @@ -1,8 +1,9 @@ -use database::{BenchmarkDB, EthereumBenchmarkWiring}; +use database::BenchmarkDB; use revm::{ bytecode::Bytecode, + handler::EthHandler, primitives::{address, bytes, hex, Bytes, TxKind}, - Evm, + Context, MainEvm, }; use std::time::Instant; @@ -13,17 +14,16 @@ pub fn run() { let bytecode_analysed = Bytecode::new_raw(contract_data).into_analyzed(); // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::::builder() - .modify_tx_env(|tx| { + let context = Context::default() + .with_db(BenchmarkDB::new_bytecode(bytecode_raw)) + .modify_tx_chained(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = address!("1000000000000000000000000000000000000000"); tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); //evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); tx.data = bytes!("8035F0CE"); - }) - .with_db(BenchmarkDB::new_bytecode(bytecode_raw)) - .with_default_ext_ctx() - .build(); + }); + let mut evm = MainEvm::new(context, EthHandler::default()); // Just to warm up the processor. for _ in 0..10000 { @@ -36,11 +36,8 @@ pub fn run() { } println!("Raw elapsed time: {:?}", timer.elapsed()); - let mut evm = evm - .modify() - .with_db(BenchmarkDB::new_bytecode(bytecode_analysed)) - .with_default_ext_ctx() - .build(); + evm.context + .modify_db(|db| *db = BenchmarkDB::new_bytecode(bytecode_analysed)); let timer = Instant::now(); for _ in 0..30000 { diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index b794b8467b..82555129f5 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -10,14 +10,12 @@ use alloy_sol_macro::sol; use alloy_sol_types::SolCall; use database::CacheDB; use revm::{ + context_interface::result::{ExecutionResult, Output}, database_interface::EmptyDB, + handler::EthHandler, primitives::{address, hex, keccak256, Address, Bytes, TxKind, B256, U256}, state::{AccountInfo, Bytecode}, - context_interface::{ - result::{ExecutionResult, Output}, - EthereumWiring, - }, - Evm, + Context, MainEvm, }; use std::fs::File; @@ -32,8 +30,6 @@ sol! { } } -type EthereumCacheDbWiring = EthereumWiring, ()>; - pub fn run() { let (seed, iterations) = try_init_env_vars().expect("Failed to parse env vars"); @@ -41,15 +37,12 @@ pub fn run() { let db = init_db(); - let mut evm = Evm::::builder() - .modify_tx_env(|tx| { - tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TxKind::Call(BURNTPIX_MAIN_ADDRESS); - tx.data = run_call_data.clone().into(); - }) - .with_db(db) - .with_default_ext_ctx() - .build(); + let context = Context::default().with_db(db).modify_tx_chained(|tx| { + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = TxKind::Call(BURNTPIX_MAIN_ADDRESS); + tx.data = run_call_data.clone().into(); + }); + let mut evm = MainEvm::new(context, EthHandler::default()); let started = Instant::now(); let tx_result = evm.transact().unwrap().result; diff --git a/bins/revme/src/cmd/bench/snailtracer.rs b/bins/revme/src/cmd/bench/snailtracer.rs index 72aa904a33..3f4368d418 100644 --- a/bins/revme/src/cmd/bench/snailtracer.rs +++ b/bins/revme/src/cmd/bench/snailtracer.rs @@ -1,24 +1,23 @@ -use database::{BenchmarkDB, EthereumBenchmarkWiring}; +use database::BenchmarkDB; use revm::{ bytecode::Bytecode, + handler::EthHandler, primitives::{address, bytes, Bytes, TxKind}, - Evm, + Context, MainEvm, }; pub fn simple_example() { let bytecode = Bytecode::new_raw(CONTRACT_DATA.clone()).into_analyzed(); - // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::::builder() + let context = Context::default() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) - .with_default_ext_ctx() - .modify_tx_env(|tx| { + .modify_tx_chained(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = address!("1000000000000000000000000000000000000000"); tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.data = bytes!("30627b7c"); - }) - .build(); + }); + let mut evm = MainEvm::new(context, EthHandler::default()); let _ = evm.transact().unwrap(); } diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index 027f1775e8..0302a92086 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -1,17 +1,16 @@ -use database::{BenchmarkDB, EthereumBenchmarkWiring}; +use database::BenchmarkDB; use revm::{ bytecode::Bytecode, + handler::EthHandler, primitives::{TxKind, U256}, - Evm, + Context, MainEvm, }; use std::time::Duration; pub fn run() { - // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::::builder() + let context = Context::default() .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) - .with_default_ext_ctx() - .modify_tx_env(|tx| { + .modify_tx_chained(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = "0x0000000000000000000000000000000000000001" .parse() @@ -22,8 +21,8 @@ pub fn run() { .parse() .unwrap(), ); - }) - .build(); + }); + let mut evm = MainEvm::new(context, EthHandler::default()); // Microbenchmark let bench_options = microbench::Options::default().time(Duration::from_secs(3)); diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 516e92a24d..2b3416dd39 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -1,10 +1,9 @@ use clap::Parser; use database::BenchmarkDB; -use inspector::{inspector_handle_register, inspectors::TracerEip3155}; +use inspector::{inspectors::TracerEip3155, InspectorMainEvm}; use revm::{ bytecode::{Bytecode, BytecodeDecodeError}, primitives::{address, hex, Address, TxKind}, - context_interface::EthereumWiring, Database, Evm, }; use std::io::Error as IoError; diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index c52b4539d0..ed61ee623f 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -408,24 +408,12 @@ pub fn execute_test_suite( .with_bundle_update() .build(); let mut evm = MainEvm { - context: Context { - block: block.clone(), - tx: tx.clone(), - cfg: cfg.clone(), - journaled_state: JournaledState::new( - cfg.spec().into(), - &mut state, - Default::default(), - ), - chain: (), - error: Ok(()), - }, - handler: EthHandler::new( - EthValidation::new(), - EthPreExecution::new(), - EthExecution::new(), - EthPostExecution::new(), - ), + context: Context::default() + .with_block(block.clone()) + .with_tx(tx.clone()) + .with_cfg(cfg.clone()) + .with_db(&mut state), + handler: EthHandler::default(), _error: core::marker::PhantomData, }; @@ -433,18 +421,11 @@ pub fn execute_test_suite( let (e, exec_result) = if trace { let mut evm = InspectorMainEvm { context: InspectorContext { - inner: Context { - block: block.clone(), - tx: tx.clone(), - cfg: cfg.clone(), - journaled_state: JournaledState::new( - cfg.spec().into(), - &mut state, - Default::default(), - ), - chain: (), - error: Ok(()), - }, + inner: Context::default() + .with_block(block.clone()) + .with_tx(tx.clone()) + .with_cfg(cfg.clone()) + .with_db(&mut state), inspector: TracerEip3155::new(Box::new(stdout())), frame_input_stack: Vec::new(), }, @@ -542,11 +523,7 @@ pub fn execute_test_suite( block: block.clone(), tx: tx.clone(), cfg: cfg.clone(), - journaled_state: JournaledState::new( - cfg.spec().into(), - &mut state, - Default::default(), - ), + journaled_state: JournaledState::new(cfg.spec().into(), &mut state), chain: (), error: Ok(()), }, diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 99a05086bf..b0486f821a 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -1,4 +1,4 @@ -use crate::{block::BlockEnv, journaled_state::JournaledState, tx::TxEnv}; +use crate::{block::BlockEnv, journaled_state::JournaledState as JournaledStateImpl, tx::TxEnv}; use bytecode::{Bytecode, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; use context_interface::{ journaled_state::{AccountLoad, Eip7702CodeLoad}, @@ -9,7 +9,7 @@ use context_interface::{ use database_interface::{Database, EmptyDB}; use derive_where::derive_where; use interpreter::{as_u64_saturated, Host, SStoreResult, SelfDestructResult, StateLoad}; -use primitives::{Address, Bytes, HashSet, Log, B256, BLOCK_HASH_HISTORY, U256}; +use primitives::{Address, Bytes, Log, B256, BLOCK_HASH_HISTORY, U256}; use specification::hardfork::SpecId; /// EVM context contains data that EVM needs for execution. @@ -22,13 +22,19 @@ pub struct Context, + pub journaled_state: JournaledStateImpl, /// Inner context. pub chain: CHAIN, /// Error that happened during execution. pub error: Result<(), ::Error>, } +impl Default for Context { + fn default() -> Self { + Self::new(EmptyDB::new(), SpecId::LATEST) + } +} + impl Context { @@ -39,13 +45,19 @@ impl Context { +impl Context +where + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, +{ /// Return account code bytes and if address is cold loaded. /// /// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code. @@ -93,6 +105,167 @@ impl Context(self, db: ODB) -> Context { + let spec = self.cfg.spec().into(); + Context { + tx: self.tx, + block: self.block, + cfg: self.cfg, + journaled_state: JournaledStateImpl::new(spec, db), + chain: self.chain, + error: Ok(()), + } + } + + /// Create a new context with a new block type. + pub fn with_block(self, block: OB) -> Context { + Context { + tx: self.tx, + block, + cfg: self.cfg, + journaled_state: self.journaled_state, + chain: self.chain, + error: Ok(()), + } + } + + /// Create a new context with a new transaction type. + pub fn with_tx(self, tx: OTX) -> Context { + Context { + tx, + block: self.block, + cfg: self.cfg, + journaled_state: self.journaled_state, + chain: self.chain, + error: Ok(()), + } + } + + /// Create a new context with a new chain type. + pub fn with_chain(self, chain: OC) -> Context { + Context { + tx: self.tx, + block: self.block, + cfg: self.cfg, + journaled_state: self.journaled_state, + chain, + error: Ok(()), + } + } + + /// Create a new context with a new chain type. + pub fn with_cfg(mut self, cfg: OCFG) -> Context { + self.journaled_state.set_spec_id(cfg.spec().into()); + Context { + tx: self.tx, + block: self.block, + cfg, + journaled_state: self.journaled_state, + chain: self.chain, + error: Ok(()), + } + } + + /// Modify the context configuration. + pub fn modify_cfg_chained(mut self, f: F) -> Self + where + F: FnOnce(&mut CFG), + { + f(&mut self.cfg); + self.journaled_state.set_spec_id(self.cfg.spec().into()); + self + } + + /// Modify the context block. + pub fn modify_block_chained(mut self, f: F) -> Self + where + F: FnOnce(&mut BLOCK), + { + self.modify_block(f); + self + } + + /// Modify the context transaction. + pub fn modify_tx_chained(mut self, f: F) -> Self + where + F: FnOnce(&mut TX), + { + self.modify_tx(f); + self + } + + /// Modify the context chain. + pub fn modify_chain_chained(mut self, f: F) -> Self + where + F: FnOnce(&mut CHAIN), + { + self.modify_chain(f); + self + } + + /// Modify the context database. + pub fn modify_db_chained(mut self, f: F) -> Self + where + F: FnOnce(&mut DB), + { + self.modify_db(f); + self + } + + /// Modify the context journal. + pub fn modify_journal_chained(mut self, f: F) -> Self + where + F: FnOnce(&mut JournaledStateImpl), + { + self.modify_journal(f); + self + } + + /// Modify the context block. + pub fn modify_block(&mut self, f: F) + where + F: FnOnce(&mut BLOCK), + { + f(&mut self.block); + } + + pub fn modify_tx(&mut self, f: F) + where + F: FnOnce(&mut TX), + { + f(&mut self.tx); + } + + pub fn modify_cfg(&mut self, f: F) + where + F: FnOnce(&mut CFG), + { + f(&mut self.cfg); + self.journaled_state.set_spec_id(self.cfg.spec().into()); + } + + pub fn modify_chain(&mut self, f: F) + where + F: FnOnce(&mut CHAIN), + { + f(&mut self.chain); + } + + pub fn modify_db(&mut self, f: F) + where + F: FnOnce(&mut DB), + { + f(&mut self.journaled_state.database); + } + + pub fn modify_journal(&mut self, f: F) + where + F: FnOnce(&mut JournaledStateImpl), + { + f(&mut self.journaled_state); + } + /// Get code hash of address. /// /// In case of EOF account it will return `EOF_MAGIC_HASH` @@ -264,7 +437,7 @@ impl CfgGetter for Context JournalStateGetter for Context { - type Journal = JournaledState; + type Journal = JournaledStateImpl; fn journal(&mut self) -> &mut Self::Journal { &mut self.journaled_state diff --git a/crates/context/src/journaled_state.rs b/crates/context/src/journaled_state.rs index fa87283ab7..a332708e03 100644 --- a/crates/context/src/journaled_state.rs +++ b/crates/context/src/journaled_state.rs @@ -176,11 +176,7 @@ impl JournaledState { /// /// This function will journal state after Spurious Dragon fork. /// And will not take into account if account is not existing or empty. - pub fn new( - spec: SpecId, - database: DB, - warm_preloaded_addresses: HashSet
, - ) -> JournaledState { + pub fn new(spec: SpecId, database: DB) -> JournaledState { Self { database, state: HashMap::default(), @@ -189,7 +185,7 @@ impl JournaledState { journal: vec![vec![]], depth: 0, spec, - warm_preloaded_addresses, + warm_preloaded_addresses: HashSet::default(), } } diff --git a/crates/handler/src/lib.rs b/crates/handler/src/lib.rs index 3f16362efb..25e76e6034 100644 --- a/crates/handler/src/lib.rs +++ b/crates/handler/src/lib.rs @@ -64,6 +64,18 @@ pub struct EthHandler< _phantom: core::marker::PhantomData (CTX, ERROR)>, } +impl Default for EthHandler { + fn default() -> Self { + Self { + validation: EthValidation::new(), + pre_execution: EthPreExecution::new(), + execution: EthExecution::new(), + post_execution: EthPostExecution::new(), + _phantom: core::marker::PhantomData, + } + } +} + impl EthHandler { diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index 3e5af7a089..a98ffb0386 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -16,9 +16,16 @@ use specification::{eip4844, hardfork::SpecId}; use state::Account; use std::boxed::Box; -#[derive(Default)] pub struct EthValidation { - pub _phantom: core::marker::PhantomData<(CTX, ERROR)>, + pub _phantom: core::marker::PhantomData (CTX, ERROR)>, +} + +impl Default for EthValidation { + fn default() -> Self { + Self { + _phantom: core::marker::PhantomData, + } + } } impl EthValidation { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 823d97dac2..764a3e372b 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -24,6 +24,16 @@ pub struct Evm> { pub _error: core::marker::PhantomData ERROR>, } +impl Evm { + pub fn new(context: CTX, handler: HANDLER) -> Self { + Self { + context, + handler, + _error: core::marker::PhantomData, + } + } +} + /// Mainnet Error. pub type Error = EVMError<::Error, InvalidTransaction>;