From 34bc8738def34f55f6ced4f09cb931a982f77f08 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 21 Jan 2025 13:10:07 +0100 Subject: [PATCH] feat: EthHandler trait (#2001) * feat: EthHandler trait * work work * frame contexts * inspector compiled * transact_main and transact_main_commit * Generalize InterpreterTypes * big cleanup, rm all partial handlers * compile * Some cleanup * some cleanup * Erc20 example, need to fix logic * fix erc20 example * cleanup and testing * fix eip7702 order, pass all devnet tests * fix compilation * docs --- Cargo.lock | 6 +- bins/revme/src/cmd/bench/analysis.rs | 8 +- bins/revme/src/cmd/bench/burntpix.rs | 8 +- bins/revme/src/cmd/bench/snailtracer.rs | 8 +- bins/revme/src/cmd/bench/transfer.rs | 9 +- bins/revme/src/cmd/evmrunner.rs | 38 +-- bins/revme/src/cmd/statetest/runner.rs | 70 ++-- crates/bytecode/src/opcode.rs | 2 +- crates/context/interface/src/context.rs | 3 + crates/context/interface/src/host.rs | 1 - .../context/interface/src/journaled_state.rs | 3 +- crates/context/interface/src/result.rs | 40 +++ crates/context/interface/src/transaction.rs | 4 - crates/context/src/journaled_state.rs | 5 +- crates/database/Cargo.toml | 1 - crates/database/src/states/cache.rs | 1 - crates/database/src/states/plain_account.rs | 2 +- crates/handler/Cargo.toml | 1 + crates/handler/interface/Cargo.toml | 2 + crates/handler/interface/src/execution.rs | 58 ---- crates/handler/interface/src/frame.rs | 14 +- crates/handler/interface/src/handler.rs | 13 - .../handler/interface/src/item_or_result.rs | 26 ++ crates/handler/interface/src/lib.rs | 16 +- .../handler/interface/src/post_execution.rs | 63 ---- crates/handler/interface/src/pre_execution.rs | 10 - .../interface/src/precompile_provider.rs | 16 +- crates/handler/interface/src/util.rs | 24 -- crates/handler/interface/src/validation.rs | 26 -- crates/handler/src/execution.rs | 249 +++----------- crates/handler/src/frame.rs | 213 ++++++------ crates/handler/src/frame_data.rs | 16 +- crates/handler/src/handler.rs | 313 ++++++++++++++++++ crates/handler/src/handler/types.rs | 144 ++++++++ crates/handler/src/lib.rs | 129 +------- crates/handler/src/post_execution.rs | 304 +++++++---------- crates/handler/src/pre_execution.rs | 160 ++++----- crates/handler/src/precompile_provider.rs | 27 +- crates/handler/src/validation.rs | 166 ++++------ crates/inspector/src/inspector.rs | 297 +++++++++-------- crates/inspector/src/inspector_context.rs | 20 +- crates/inspector/src/inspector_instruction.rs | 70 +++- crates/interpreter/CHANGELOG.md | 2 +- crates/interpreter/Cargo.toml | 1 - crates/interpreter/src/gas/calc.rs | 11 +- crates/interpreter/src/instructions.rs | 1 - crates/interpreter/src/instructions/stack.rs | 1 - crates/interpreter/src/interpreter.rs | 51 +-- crates/interpreter/src/interpreter/stack.rs | 2 +- crates/interpreter/src/lib.rs | 2 +- crates/optimism/Cargo.toml | 2 +- crates/optimism/src/evm.rs | 48 --- crates/optimism/src/handler.rs | 221 ++++--------- crates/optimism/src/handler/precompiles.rs | 77 +++-- crates/optimism/src/lib.rs | 1 - crates/optimism/src/spec.rs | 8 + crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 7 - crates/revm/src/evm.rs | 307 ++--------------- crates/revm/src/lib.rs | 6 +- examples/block_traces/src/main.rs | 64 ++-- examples/cheatcode_inspector/src/main.rs | 98 +----- examples/contract_deployment/src/main.rs | 24 +- examples/erc20_gas/src/exec.rs | 27 ++ examples/erc20_gas/src/handler.rs | 189 +++++++++++ examples/erc20_gas/src/handlers/mod.rs | 34 -- .../erc20_gas/src/handlers/post_execution.rs | 119 ------- .../erc20_gas/src/handlers/pre_execution.rs | 63 ---- examples/erc20_gas/src/handlers/validation.rs | 106 ------ examples/erc20_gas/src/main.rs | 167 +++------- examples/uniswap_get_reserves/src/main.rs | 43 +-- examples/uniswap_v2_usdc_swap/src/main.rs | 122 +++---- graph.png | Bin 0 -> 334974 bytes 73 files changed, 1848 insertions(+), 2544 deletions(-) delete mode 100644 crates/handler/interface/src/execution.rs delete mode 100644 crates/handler/interface/src/handler.rs create mode 100644 crates/handler/interface/src/item_or_result.rs delete mode 100644 crates/handler/interface/src/post_execution.rs delete mode 100644 crates/handler/interface/src/pre_execution.rs delete mode 100644 crates/handler/interface/src/util.rs delete mode 100644 crates/handler/interface/src/validation.rs create mode 100644 crates/handler/src/handler.rs create mode 100644 crates/handler/src/handler/types.rs delete mode 100644 crates/optimism/src/evm.rs create mode 100644 examples/erc20_gas/src/exec.rs create mode 100644 examples/erc20_gas/src/handler.rs delete mode 100644 examples/erc20_gas/src/handlers/mod.rs delete mode 100644 examples/erc20_gas/src/handlers/post_execution.rs delete mode 100644 examples/erc20_gas/src/handlers/pre_execution.rs delete mode 100644 examples/erc20_gas/src/handlers/validation.rs create mode 100644 graph.png diff --git a/Cargo.lock b/Cargo.lock index bb698ec97a..b7ee6e07af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3457,7 +3457,6 @@ dependencies = [ "auto_impl", "indicatif", "revm-bytecode", - "revm-context-interface", "revm-database-interface", "revm-primitives", "revm-state", @@ -3487,6 +3486,7 @@ name = "revm-handler" version = "1.0.0" dependencies = [ "revm-bytecode", + "revm-context", "revm-context-interface", "revm-database", "revm-handler-interface", @@ -3502,8 +3502,10 @@ dependencies = [ name = "revm-handler-interface" version = "1.0.0" dependencies = [ + "auto_impl", "revm-database", "revm-primitives", + "revm-specification", ] [[package]] @@ -3525,7 +3527,6 @@ dependencies = [ "revm-bytecode", "revm-context-interface", "revm-database-interface", - "revm-handler-interface", "revm-primitives", "revm-specification", "serde", @@ -3543,7 +3544,6 @@ dependencies = [ "once_cell", "revm", "revm-database", - "revm-inspector", "revm-precompile", "rstest 0.23.0", "serde", diff --git a/bins/revme/src/cmd/bench/analysis.rs b/bins/revme/src/cmd/bench/analysis.rs index 246cd4240a..88219799c7 100644 --- a/bins/revme/src/cmd/bench/analysis.rs +++ b/bins/revme/src/cmd/bench/analysis.rs @@ -1,9 +1,8 @@ use database::BenchmarkDB; use revm::{ bytecode::Bytecode, - handler::EthHandler, primitives::{address, bytes, hex, Bytes, TxKind}, - Context, MainEvm, + transact_main, Context, }; const BYTES: &str = include_str!("analysis.hex"); @@ -12,7 +11,7 @@ pub fn run() { let bytecode = Bytecode::new_raw(Bytes::from(hex::decode(BYTES).unwrap())); // BenchmarkDB is dummy state that implements Database trait. - let context = Context::builder() + let mut context = Context::builder() .with_db(BenchmarkDB::new_bytecode(bytecode)) .modify_tx_chained(|tx| { // Execution globals block hash/gas_limit/coinbase/timestamp.. @@ -21,6 +20,5 @@ pub fn run() { //evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); tx.data = bytes!("8035F0CE"); }); - let mut evm = MainEvm::new(context, EthHandler::default()); - let _ = evm.transact().unwrap(); + let _ = transact_main(&mut context); } diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index c1a6158719..b8f922a823 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -12,10 +12,9 @@ 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, MainEvm, + transact_main, Context, }; use std::fs::File; @@ -37,16 +36,15 @@ pub fn run() { let db = init_db(); - let context = Context::builder().with_db(db).modify_tx_chained(|tx| { + let mut context = Context::builder().with_db(db).modify_tx_chained(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); tx.kind = TxKind::Call(BURNTPIX_MAIN_ADDRESS); tx.data = run_call_data.clone().into(); tx.gas_limit = u64::MAX; }); - let mut evm = MainEvm::new(context, EthHandler::default()); let started = Instant::now(); - let tx_result = evm.transact().unwrap().result; + let tx_result = transact_main(&mut context).unwrap().result; let return_data = match tx_result { ExecutionResult::Success { output, gas_used, .. diff --git a/bins/revme/src/cmd/bench/snailtracer.rs b/bins/revme/src/cmd/bench/snailtracer.rs index 4d3a75a8fe..8fd548614a 100644 --- a/bins/revme/src/cmd/bench/snailtracer.rs +++ b/bins/revme/src/cmd/bench/snailtracer.rs @@ -1,13 +1,12 @@ use database::BenchmarkDB; use revm::{ bytecode::Bytecode, - handler::EthHandler, primitives::{address, bytes, hex, Bytes, TxKind}, - Context, MainEvm, + transact_main, Context, }; pub fn simple_example(bytecode: Bytecode) { - let context = Context::builder() + let mut context = Context::builder() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .modify_tx_chained(|tx| { // Execution globals block hash/gas_limit/coinbase/timestamp.. @@ -16,8 +15,7 @@ pub fn simple_example(bytecode: Bytecode) { tx.data = bytes!("30627b7c"); tx.gas_limit = 1_000_000_000; }); - let mut evm = MainEvm::new(context, EthHandler::default()); - let _ = evm.transact().unwrap(); + let _ = transact_main(&mut context).unwrap(); } pub fn run() { diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index 6363c00c3c..9ffffdc150 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -1,13 +1,12 @@ use database::BenchmarkDB; use revm::{ bytecode::Bytecode, - handler::EthHandler, primitives::{TxKind, U256}, - Context, MainEvm, + transact_main, Context, }; pub fn run() { - let context = Context::builder() + let mut context = Context::builder() .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) .modify_tx_chained(|tx| { // Execution globals block hash/gas_limit/coinbase/timestamp.. @@ -21,7 +20,5 @@ pub fn run() { .unwrap(), ); }); - let mut evm = MainEvm::new(context, EthHandler::default()); - - let _ = evm.transact().unwrap(); + let _ = transact_main(&mut context); } diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 2ad8a2a9fc..a379596bb4 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -1,14 +1,10 @@ use clap::Parser; use database::BenchmarkDB; -use inspector::{ - inspector_context::InspectorContext, inspector_handler, inspectors::TracerEip3155, - InspectorMainEvm, -}; +use inspector::{inspect_main, inspector_context::InspectorContext, inspectors::TracerEip3155}; use revm::{ bytecode::{Bytecode, BytecodeDecodeError}, - handler::EthHandler, primitives::{address, hex, Address, TxKind}, - Context, Database, EvmExec, MainEvm, + transact_main, Context, Database, }; use std::io::Error as IoError; use std::path::PathBuf; @@ -86,36 +82,32 @@ impl Cmd { // BenchmarkDB is dummy state that implements Database trait. // The bytecode is deployed at zero address. - let mut evm = MainEvm::new( - Context::builder().with_db(db).modify_tx_chained(|tx| { - tx.caller = CALLER; - tx.kind = TxKind::Call(Address::ZERO); - tx.data = input; - tx.nonce = nonce; - }), - EthHandler::default(), - ); + let mut ctx = Context::builder().with_db(db).modify_tx_chained(|tx| { + tx.caller = CALLER; + tx.kind = TxKind::Call(Address::ZERO); + tx.data = input; + tx.nonce = nonce; + }); if self.bench { // Microbenchmark let bench_options = microbench::Options::default().time(Duration::from_secs(3)); microbench::bench(&bench_options, "Run bytecode", || { - let _ = evm.transact().unwrap(); + let _ = transact_main(&mut ctx).unwrap(); }); return Ok(()); } let out = if self.trace { - let mut evm = InspectorMainEvm::new( - InspectorContext::new(evm.context, TracerEip3155::new(Box::new(std::io::stdout()))), - inspector_handler(), - ); - - evm.exec().map_err(|_| Errors::EVMError)? + inspect_main(&mut InspectorContext::new( + &mut ctx, + TracerEip3155::new(Box::new(std::io::stdout())), + )) + .map_err(|_| Errors::EVMError)? } else { - let out = evm.transact().map_err(|_| Errors::EVMError)?; + let out = transact_main(&mut ctx).map_err(|_| Errors::EVMError)?; println!("Result: {:#?}", out.result); out }; diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 9d5f01c4a9..f02597a60a 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -5,8 +5,7 @@ use super::{ use database::State; use indicatif::{ProgressBar, ProgressDrawTarget}; use inspector::{ - inspector_context::InspectorContext, inspector_handler, inspectors::TracerEip3155, - InspectorMainEvm, + inspect_main_commit, inspector_context::InspectorContext, inspectors::TracerEip3155, }; use revm::{ bytecode::Bytecode, @@ -17,10 +16,9 @@ use revm::{ Cfg, }, database_interface::EmptyDB, - handler::EthHandler, primitives::{keccak256, Bytes, TxKind, B256}, specification::{eip4844::TARGET_BLOB_GAS_PER_BLOCK_CANCUN, hardfork::SpecId}, - Context, DatabaseCommit, EvmCommit, MainEvm, + transact_main_commit, Context, }; use serde_json::json; use statetest_types::{SpecName, Test, TestSuite}; @@ -361,7 +359,6 @@ pub fn execute_test_suite( } for (index, test) in tests.into_iter().enumerate() { - // TODO : TX TYPE needs to be set let Some(tx_type) = unit.transaction.tx_type(test.indexes.data) else { if test.expect_exception.is_some() { continue; @@ -416,35 +413,29 @@ pub fn execute_test_suite( .with_cached_prestate(cache) .with_bundle_update() .build(); - let mut evm = MainEvm::new( - Context::builder() - .with_block(&block) - .with_tx(&tx) - .with_cfg(&cfg) - .with_db(&mut state), - EthHandler::default(), - ); + let mut ctx = Context::builder() + .with_block(&block) + .with_tx(&tx) + .with_cfg(&cfg) + .with_db(&mut state); // Do the deed let (e, exec_result) = if trace { - let mut evm = InspectorMainEvm::new( - InspectorContext::new( - Context::builder() - .with_block(&block) - .with_tx(&tx) - .with_cfg(&cfg) - .with_db(&mut state), - TracerEip3155::new(Box::new(stderr())).without_summary(), - ), - inspector_handler(), + let mut ctx = &mut InspectorContext::new( + Context::builder() + .with_block(&block) + .with_tx(&tx) + .with_cfg(&cfg) + .with_db(&mut state), + TracerEip3155::new(Box::new(stderr())).without_summary(), ); let timer = Instant::now(); - let res = evm.exec_commit(); + let res = inspect_main_commit(&mut ctx); *elapsed.lock().unwrap() += timer.elapsed(); let spec = cfg.spec(); - let db = evm.context.inner.journaled_state.database; + let db = &mut ctx.inner.journaled_state.database; // Dump state and traces if test failed let output = check_evm_execution( &test, @@ -461,11 +452,11 @@ pub fn execute_test_suite( (e, res) } else { let timer = Instant::now(); - let res = evm.exec_commit(); + let res = transact_main_commit(&mut ctx); *elapsed.lock().unwrap() += timer.elapsed(); let spec = cfg.spec(); - let db = evm.context.journaled_state.database; + let db = ctx.journaled_state.database; // Dump state and traces if test failed let output = check_evm_execution( &test, @@ -503,30 +494,23 @@ pub fn execute_test_suite( println!("\nTraces:"); - let mut evm = InspectorMainEvm::new( - InspectorContext::new( - Context::builder() - .with_db(&mut state) - .with_block(&block) - .with_tx(&tx) - .with_cfg(&cfg), - TracerEip3155::new(Box::new(stderr())).without_summary(), - ), - inspector_handler(), + let mut ctx = InspectorContext::new( + Context::builder() + .with_db(&mut state) + .with_block(&block) + .with_tx(&tx) + .with_cfg(&cfg), + TracerEip3155::new(Box::new(stderr())).without_summary(), ); - let res = evm.transact(); - let _ = res.map(|r| { - evm.context.inner.journaled_state.database.commit(r.state); - r.result - }); + let _ = inspect_main_commit(&mut ctx); println!("\nExecution result: {exec_result:#?}"); println!("\nExpected exception: {:?}", test.expect_exception); println!("\nState before: {cache_state:#?}"); println!( "\nState after: {:#?}", - evm.context.inner.journaled_state.database.cache + ctx.inner.journaled_state.database.cache ); println!("\nSpecification: {:?}", cfg.spec); println!("\nTx: {tx:#?}"); diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index e33f3eb349..47d7abe0e6 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -784,7 +784,7 @@ mod tests { assert_eq!( opcode.map(|opcode| opcode.terminating).unwrap_or_default(), opcodes[i], - "Opcode {:?} terminating chack failed.", + "Opcode {:?} terminating check failed.", opcode ); } diff --git a/crates/context/interface/src/context.rs b/crates/context/interface/src/context.rs index 3378775607..a704965032 100644 --- a/crates/context/interface/src/context.rs +++ b/crates/context/interface/src/context.rs @@ -1,9 +1,12 @@ +use auto_impl::auto_impl; + /// Some actions on top of context with just Getter traits would require borrowing the context /// with a both mutable and immutable reference. /// /// To allow doing this action more efficiently, we introduce a new trait that does this directly. /// /// Used for loading access list and applying EIP-7702 authorization list. +#[auto_impl(&mut,Box)] pub trait PerformantContextAccess { type Error; diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index 89dd40eba3..fce7a768f5 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -8,7 +8,6 @@ use auto_impl::auto_impl; use primitives::{Address, Bytes, Log, B256, U256}; /// EVM context host. -// TODO : Move to context-interface #[auto_impl(&mut, Box)] pub trait Host: TransactionGetter + BlockGetter + CfgGetter { /// Load an account code. diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 6681a3b6a6..9f6734845b 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -71,7 +71,6 @@ pub trait Journal { fn touch_account(&mut self, address: Address); - // TODO : Instruction result is not known fn transfer( &mut self, from: &Address, @@ -133,7 +132,7 @@ pub trait Journal { /// Does cleanup and returns modified state. /// /// This resets the [Journal] to its initial state. - fn finalize(&mut self) -> Result::Error>; + fn finalize(&mut self) -> Self::FinalOutput; } /// Transfer and creation result diff --git a/crates/context/interface/src/result.rs b/crates/context/interface/src/result.rs index 29bd64d6d1..c8cd35703b 100644 --- a/crates/context/interface/src/result.rs +++ b/crates/context/interface/src/result.rs @@ -21,6 +21,19 @@ pub struct ResultAndState { pub state: EvmState, } +impl ResultAndState { + /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged. + pub fn map_haltreason(self, op: F) -> ResultAndState + where + F: FnOnce(HaltReasonT) -> OHR, + { + ResultAndState { + result: self.result.map_haltreason(op), + state: self.state, + } + } +} + /// Result of a transaction execution #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -53,6 +66,33 @@ impl ExecutionResult { matches!(self, Self::Success { .. }) } + /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged. + pub fn map_haltreason(self, op: F) -> ExecutionResult + where + F: FnOnce(HaltReasonT) -> OHR, + { + match self { + Self::Success { + reason, + gas_used, + gas_refunded, + logs, + output, + } => ExecutionResult::Success { + reason, + gas_used, + gas_refunded, + logs, + output, + }, + Self::Revert { gas_used, output } => ExecutionResult::Revert { gas_used, output }, + Self::Halt { reason, gas_used } => ExecutionResult::Halt { + reason: op(reason), + gas_used, + }, + } + } + /// Returns created address if execution is Create transaction /// and Contract was created. pub fn created_address(&self) -> Option
{ diff --git a/crates/context/interface/src/transaction.rs b/crates/context/interface/src/transaction.rs index a4790e055f..983ee0126e 100644 --- a/crates/context/interface/src/transaction.rs +++ b/crates/context/interface/src/transaction.rs @@ -95,8 +95,6 @@ pub trait Transaction { /// Total gas for all blobs. Max number of blocks is already checked /// so we dont need to check for overflow. - /// - /// TODO remove this fn total_blob_gas(&self) -> u64 { GAS_PER_BLOB * self.blob_versioned_hashes().len() as u64 } @@ -108,8 +106,6 @@ pub trait Transaction { /// /// See EIP-4844: /// - /// - /// TODO remove it, make a utility trait. fn calc_max_data_fee(&self) -> U256 { let blob_gas = U256::from(self.total_blob_gas()); let max_blob_fee = U256::from(self.max_fee_per_blob_gas()); diff --git a/crates/context/src/journaled_state.rs b/crates/context/src/journaled_state.rs index c8d8451123..6c8ef8e7ef 100644 --- a/crates/context/src/journaled_state.rs +++ b/crates/context/src/journaled_state.rs @@ -150,7 +150,6 @@ impl Journal for JournaledState { to: &Address, balance: U256, ) -> Result, DB::Error> { - // TODO : Handle instruction result self.transfer(from, to, balance) } @@ -217,7 +216,7 @@ impl Journal for JournaledState { self.create_account_checkpoint(caller, address, balance, spec_id) } - fn finalize(&mut self) -> Result::Error> { + fn finalize(&mut self) -> Self::FinalOutput { let Self { state, transient_storage, @@ -237,7 +236,7 @@ impl Journal for JournaledState { let state = mem::take(state); let logs = mem::take(logs); - Ok((state, logs)) + (state, logs) } } diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index cb27f93992..d547c778f0 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -25,7 +25,6 @@ all = "warn" state.workspace = true primitives.workspace = true database-interface.workspace = true -context-interface.workspace = true bytecode.workspace = true auto_impl = "1.2" diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index 2b9f29413c..9105f974cd 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -19,7 +19,6 @@ pub struct CacheState { /// Block state account with account state pub accounts: HashMap, /// Created contracts - // TODO : Add bytecode counter for number of bytecodes added/removed. pub contracts: HashMap, /// Has EIP-161 state clear enabled (Spurious Dragon hardfork) pub has_state_clear: bool, diff --git a/crates/database/src/states/plain_account.rs b/crates/database/src/states/plain_account.rs index 547896e148..0d54a46854 100644 --- a/crates/database/src/states/plain_account.rs +++ b/crates/database/src/states/plain_account.rs @@ -1,7 +1,7 @@ use primitives::{HashMap, U256}; use state::{AccountInfo, EvmStorageSlot}; -// TODO : Rename this to BundleAccount. As for the block level we have original state. +// Plain account of StateDatabase. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct PlainAccount { pub info: AccountInfo, diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 3037d07d0c..3ce214fc13 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -26,6 +26,7 @@ all = "warn" interpreter.workspace = true precompile.workspace = true context-interface.workspace = true +context.workspace = true primitives.workspace = true state.workspace = true specification.workspace = true diff --git a/crates/handler/interface/Cargo.toml b/crates/handler/interface/Cargo.toml index 5c7c59b98c..af2f083308 100644 --- a/crates/handler/interface/Cargo.toml +++ b/crates/handler/interface/Cargo.toml @@ -24,6 +24,8 @@ all = "warn" [dependencies] # revm primitives.workspace = true +auto_impl.workspace = true +specification.workspace = true [dev-dependencies] database.workspace = true diff --git a/crates/handler/interface/src/execution.rs b/crates/handler/interface/src/execution.rs deleted file mode 100644 index 19e4bd3e54..0000000000 --- a/crates/handler/interface/src/execution.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::util::FrameOrFrameResult; -pub use crate::{Frame, FrameOrResultGen}; -pub use std::{vec, vec::Vec}; - -pub trait ExecutionHandler { - type Context; - type Error; - type Frame: Frame; - type ExecResult; - - /// Execute call. - fn init_first_frame( - &mut self, - context: &mut Self::Context, - gas_limit: u64, - ) -> Result, Self::Error>; - - /// Execute create. - fn last_frame_result( - &self, - context: &mut Self::Context, - frame_result: ::FrameResult, - ) -> Result; - - fn run( - &self, - context: &mut Self::Context, - frame: Self::Frame, - ) -> Result { - let mut frame_stack: Vec<::Frame> = vec![frame]; - loop { - let frame = frame_stack.last_mut().unwrap(); - let call_or_result = frame.run(context)?; - - let mut result = match call_or_result { - FrameOrResultGen::Frame(init) => match frame.init(context, init)? { - FrameOrResultGen::Frame(new_frame) => { - frame_stack.push(new_frame); - continue; - } - // Dont pop the frame as new frame was not created. - FrameOrResultGen::Result(result) => result, - }, - FrameOrResultGen::Result(result) => { - // Pop frame that returned result - frame_stack.pop(); - result - } - }; - - let Some(frame) = frame_stack.last_mut() else { - Self::Frame::final_return(context, &mut result)?; - return self.last_frame_result(context, result); - }; - frame.return_result(context, result)?; - } - } -} diff --git a/crates/handler/interface/src/frame.rs b/crates/handler/interface/src/frame.rs index 6012946dc1..6d20521d69 100644 --- a/crates/handler/interface/src/frame.rs +++ b/crates/handler/interface/src/frame.rs @@ -1,36 +1,42 @@ -use crate::FrameOrResultGen; +use crate::{FrameInitOrResult, FrameOrResult}; /// Call frame trait pub trait Frame: Sized { type Context; type FrameInit; + type FrameContext; type FrameResult; type Error; fn init_first( context: &mut Self::Context, + frame_context: &mut Self::FrameContext, frame_input: Self::FrameInit, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; fn final_return( context: &mut Self::Context, + frame_context: &mut Self::FrameContext, result: &mut Self::FrameResult, ) -> Result<(), Self::Error>; fn init( &self, context: &mut Self::Context, + frame_context: &mut Self::FrameContext, frame_input: Self::FrameInit, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; fn run( &mut self, context: &mut Self::Context, - ) -> Result, Self::Error>; + frame_context: &mut Self::FrameContext, + ) -> Result, Self::Error>; fn return_result( &mut self, context: &mut Self::Context, + frame_context: &mut Self::FrameContext, result: Self::FrameResult, ) -> Result<(), Self::Error>; } diff --git a/crates/handler/interface/src/handler.rs b/crates/handler/interface/src/handler.rs deleted file mode 100644 index c33ead7c20..0000000000 --- a/crates/handler/interface/src/handler.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}; - -pub trait Handler { - type Validation: ValidationHandler; - type PreExecution: PreExecutionHandler; - type Execution: ExecutionHandler; - type PostExecution: PostExecutionHandler; - - fn validation(&mut self) -> &mut Self::Validation; - fn pre_execution(&mut self) -> &mut Self::PreExecution; - fn execution(&mut self) -> &mut Self::Execution; - fn post_execution(&mut self) -> &mut Self::PostExecution; -} diff --git a/crates/handler/interface/src/item_or_result.rs b/crates/handler/interface/src/item_or_result.rs new file mode 100644 index 0000000000..ed07a470c1 --- /dev/null +++ b/crates/handler/interface/src/item_or_result.rs @@ -0,0 +1,26 @@ +use crate::Frame; + +pub enum ItemOrResult { + Item(ITEM), + Result(RES), +} + +impl ItemOrResult { + pub fn map_frame(self, f: impl FnOnce(ITEM) -> OITEM) -> ItemOrResult { + match self { + ItemOrResult::Item(item) => ItemOrResult::Item(f(item)), + ItemOrResult::Result(result) => ItemOrResult::Result(result), + } + } + + pub fn map_result(self, f: impl FnOnce(RES) -> ORES) -> ItemOrResult { + match self { + ItemOrResult::Item(item) => ItemOrResult::Item(item), + ItemOrResult::Result(result) => ItemOrResult::Result(f(result)), + } + } +} + +pub type FrameOrResult = ItemOrResult::FrameResult>; +pub type FrameInitOrResult = + ItemOrResult<::FrameInit, ::FrameResult>; diff --git a/crates/handler/interface/src/lib.rs b/crates/handler/interface/src/lib.rs index fc133891e5..81ac9cef59 100644 --- a/crates/handler/interface/src/lib.rs +++ b/crates/handler/interface/src/lib.rs @@ -5,20 +5,10 @@ #[cfg(not(feature = "std"))] extern crate alloc as std; -pub mod execution; pub mod frame; -pub mod handler; -pub mod post_execution; -pub mod pre_execution; +pub mod item_or_result; pub mod precompile_provider; -pub mod util; -pub mod validation; -pub use execution::ExecutionHandler; pub use frame::Frame; -pub use handler::Handler; -pub use post_execution::PostExecutionHandler; -pub use pre_execution::PreExecutionHandler; -pub use precompile_provider::PrecompileProvider; -pub use util::FrameOrResultGen; -pub use validation::{InitialAndFloorGas, ValidationHandler}; +pub use item_or_result::{FrameInitOrResult, FrameOrResult, ItemOrResult}; +pub use precompile_provider::{PrecompileProvider, PrecompileProviderGetter}; diff --git a/crates/handler/interface/src/post_execution.rs b/crates/handler/interface/src/post_execution.rs deleted file mode 100644 index 73bd7ec991..0000000000 --- a/crates/handler/interface/src/post_execution.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::InitialAndFloorGas; - -pub trait PostExecutionHandler { - type Context; - type Error; - type ExecResult; - type Output; - - /// Calculate final refund. - fn eip7623_check_gas_floor( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - init_and_floor_gas: InitialAndFloorGas, - ); - - /// Calculate final refund. - fn refund( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - eip7702_refund: i64, - ); - - /// Reimburse the caller with balance it didn't spent. - fn reimburse_caller( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error>; - - /// Reward beneficiary with transaction rewards. - fn reward_beneficiary( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error>; - - /// Main return handle, takes state from journal and transforms internal result to [`Output`][PostExecutionHandler::Output]. - fn output( - &self, - context: &mut Self::Context, - result: Self::ExecResult, - ) -> Result; - - /// Called when execution ends. - /// - /// End handle in comparison to output handle will be called every time after execution. - /// - /// While [`output`][PostExecutionHandler::output] will be omitted in case of the error. - fn end( - &self, - _context: &mut Self::Context, - end_output: Result, - ) -> Result { - end_output - } - - /// Clean handler. - /// - /// This handle is called every time regardless of the result of the transaction. - fn clear(&self, context: &mut Self::Context); -} diff --git a/crates/handler/interface/src/pre_execution.rs b/crates/handler/interface/src/pre_execution.rs deleted file mode 100644 index 9afe508d99..0000000000 --- a/crates/handler/interface/src/pre_execution.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub trait PreExecutionHandler { - type Context; - type Error; - - fn load_accounts(&self, context: &mut Self::Context) -> Result<(), Self::Error>; - - fn apply_eip7702_auth_list(&self, context: &mut Self::Context) -> Result; - - fn deduct_caller(&self, context: &mut Self::Context) -> Result<(), Self::Error>; -} diff --git a/crates/handler/interface/src/precompile_provider.rs b/crates/handler/interface/src/precompile_provider.rs index b2f8142bd1..e7a15f5885 100644 --- a/crates/handler/interface/src/precompile_provider.rs +++ b/crates/handler/interface/src/precompile_provider.rs @@ -1,12 +1,16 @@ +use auto_impl::auto_impl; use primitives::{Address, Bytes}; +use specification::hardfork::SpecId; +use std::boxed::Box; +#[auto_impl(&mut, Box)] pub trait PrecompileProvider: Clone { type Context; type Output; type Error; + type Spec: Into; - /// Create a new precompile. - fn new(context: &mut Self::Context) -> Self; + fn set_spec(&mut self, spec: Self::Spec); /// Run the precompile. fn run( @@ -18,8 +22,14 @@ pub trait PrecompileProvider: Clone { ) -> Result, Self::Error>; /// Get the warm addresses. - fn warm_addresses(&self) -> impl Iterator; + fn warm_addresses(&self) -> Box + '_>; /// Check if the address is a precompile. fn contains(&self, address: &Address) -> bool; } + +pub trait PrecompileProviderGetter { + type PrecompileProvider: PrecompileProvider; + + fn precompiles(&mut self) -> &mut Self::PrecompileProvider; +} diff --git a/crates/handler/interface/src/util.rs b/crates/handler/interface/src/util.rs deleted file mode 100644 index 560d8341bc..0000000000 --- a/crates/handler/interface/src/util.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::Frame; - -pub enum FrameOrResultGen { - Frame(Frame), - Result(Result), -} - -impl FrameOrResultGen { - pub fn map_frame(self, f: impl FnOnce(F) -> F2) -> FrameOrResultGen { - match self { - FrameOrResultGen::Frame(frame) => FrameOrResultGen::Frame(f(frame)), - FrameOrResultGen::Result(result) => FrameOrResultGen::Result(result), - } - } - - pub fn map_result(self, f: impl FnOnce(R) -> R2) -> FrameOrResultGen { - match self { - FrameOrResultGen::Frame(frame) => FrameOrResultGen::Frame(frame), - FrameOrResultGen::Result(result) => FrameOrResultGen::Result(f(result)), - } - } -} - -pub type FrameOrFrameResult = FrameOrResultGen::FrameResult>; diff --git a/crates/handler/interface/src/validation.rs b/crates/handler/interface/src/validation.rs deleted file mode 100644 index 5f45c15677..0000000000 --- a/crates/handler/interface/src/validation.rs +++ /dev/null @@ -1,26 +0,0 @@ -pub trait ValidationHandler { - type Context; - type Error; - - /// Validate env. - fn validate_env(&self, context: &Self::Context) -> Result<(), Self::Error>; - - /// Validate transactions against state. - fn validate_tx_against_state(&self, context: &mut Self::Context) -> Result<(), Self::Error>; - - /// Validate initial gas. - fn validate_initial_tx_gas( - &self, - context: &Self::Context, - ) -> Result; -} - -/// Init and floor gas from transaction -#[derive(Clone, Copy, Debug, Default)] -pub struct InitialAndFloorGas { - /// Initial gas for transaction. - pub initial_gas: u64, - /// If transaction is a Call and Prague is enabled - /// floor_gas is at least amount of gas that is going to be spent. - pub floor_gas: u64, -} diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index 6b3bbd3e52..9218ad025a 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -1,12 +1,7 @@ -use super::{frame_data::FrameResult, EthFrame, EthPrecompileProvider}; +use super::frame_data::FrameResult; use bytecode::EOF_MAGIC_BYTES; -use context_interface::{ - result::InvalidTransaction, BlockGetter, Cfg, CfgGetter, ErrorGetter, JournalDBError, - JournalGetter, Transaction, TransactionGetter, -}; -use handler_interface::{util::FrameOrFrameResult, ExecutionHandler, Frame as FrameTrait}; +use context_interface::{Transaction, TransactionGetter}; use interpreter::{ - interpreter::{EthInstructionProvider, EthInterpreter}, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInputs, EOFCreateKind, FrameInput, Gas, }; @@ -14,204 +9,60 @@ use primitives::TxKind; use specification::hardfork::SpecId; use std::boxed::Box; -#[derive(Default)] -pub struct EthExecution< - CTX, - ERROR, - FRAME = EthFrame< - CTX, - ERROR, - EthInterpreter<()>, - EthPrecompileProvider, - EthInstructionProvider, CTX>, - >, -> { - _phantom: core::marker::PhantomData<(CTX, FRAME, ERROR)>, -} - -impl ExecutionHandler for EthExecution -where - CTX: EthExecutionContext, - ERROR: EthExecutionError, - FRAME: - FrameTrait, -{ - type Context = CTX; - type Error = ERROR; - type Frame = FRAME; - type ExecResult = FrameResult; - - fn init_first_frame( - &mut self, - context: &mut Self::Context, - gas_limit: u64, - ) -> Result, Self::Error> { - // Make new frame action. - let spec = context.cfg().spec().into(); - let tx = context.tx(); - let input = tx.input().clone(); - - let init_frame: FrameInput = match tx.kind() { - TxKind::Call(target_address) => FrameInput::Call(Box::new(CallInputs { - input, - gas_limit, - target_address, - bytecode_address: target_address, - caller: tx.caller(), - value: CallValue::Transfer(tx.value()), - scheme: CallScheme::Call, - is_static: false, - is_eof: false, - return_memory_offset: 0..0, - })), - TxKind::Create => { - // If first byte of data is magic 0xEF00, then it is EOFCreate. - if spec.is_enabled_in(SpecId::OSAKA) && input.starts_with(&EOF_MAGIC_BYTES) { - FrameInput::EOFCreate(Box::new(EOFCreateInputs::new( - tx.caller(), - tx.value(), - gas_limit, - EOFCreateKind::Tx { initdata: input }, - ))) - } else { - FrameInput::Create(Box::new(CreateInputs { - caller: tx.caller(), - scheme: CreateScheme::Create, - value: tx.value(), - init_code: input, - gas_limit, - })) - } +pub fn create_init_frame(tx: &impl Transaction, spec: SpecId, gas_limit: u64) -> FrameInput { + // Make new frame action. + let input = tx.input().clone(); + + match tx.kind() { + TxKind::Call(target_address) => FrameInput::Call(Box::new(CallInputs { + input, + gas_limit, + target_address, + bytecode_address: target_address, + caller: tx.caller(), + value: CallValue::Transfer(tx.value()), + scheme: CallScheme::Call, + is_static: false, + is_eof: false, + return_memory_offset: 0..0, + })), + TxKind::Create => { + // If first byte of data is magic 0xEF00, then it is EOFCreate. + if spec.is_enabled_in(SpecId::OSAKA) && input.starts_with(&EOF_MAGIC_BYTES) { + FrameInput::EOFCreate(Box::new(EOFCreateInputs::new( + tx.caller(), + tx.value(), + gas_limit, + EOFCreateKind::Tx { initdata: input }, + ))) + } else { + FrameInput::Create(Box::new(CreateInputs { + caller: tx.caller(), + scheme: CreateScheme::Create, + value: tx.value(), + init_code: input, + gas_limit, + })) } - }; - FRAME::init_first(context, init_frame) - } - - fn last_frame_result( - &self, - context: &mut Self::Context, - mut frame_result: ::FrameResult, - ) -> Result { - let instruction_result = frame_result.interpreter_result().result; - let gas = frame_result.gas_mut(); - let remaining = gas.remaining(); - let refunded = gas.refunded(); - - // Spend the gas limit. Gas is reimbursed when the tx returns successfully. - *gas = Gas::new_spent(context.tx().gas_limit()); - - if instruction_result.is_ok_or_revert() { - gas.erase_cost(remaining); - } - - if instruction_result.is_ok() { - gas.record_refund(refunded); } - - Ok(frame_result) } } -impl EthExecution { - pub fn new() -> Self { - Self { - _phantom: core::marker::PhantomData, - } - } +/// TODO : Frame result should be a generic trait with needed functions. +pub fn last_frame_result(context: CTX, frame_result: &mut FrameResult) { + let instruction_result = frame_result.interpreter_result().result; + let gas = frame_result.gas_mut(); + let remaining = gas.remaining(); + let refunded = gas.refunded(); - pub fn new_boxed() -> Box { - Box::new(Self::new()) - } -} + // Spend the gas limit. Gas is reimbursed when the tx returns successfully. + *gas = Gas::new_spent(context.tx().gas_limit()); -pub trait EthExecutionContext: - TransactionGetter - + ErrorGetter> - + BlockGetter - + JournalGetter - + CfgGetter -{ -} - -impl< - ERROR, - T: TransactionGetter - + ErrorGetter> - + BlockGetter - + JournalGetter - + CfgGetter, - > EthExecutionContext for T -{ -} - -pub trait EthExecutionError: - From + From> -{ -} + if instruction_result.is_ok_or_revert() { + gas.erase_cost(remaining); + } -impl + From>> - EthExecutionError for T -{ + if instruction_result.is_ok() { + gas.record_refund(refunded); + } } - -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::handler::mainnet::refund; -// use interpreter::InstructionResult; -// use primitives::Bytes; -// use specification::hardfork::CancunSpec; -// use context_interface::{default::EnvWiring, DefaultEthereumWiring}; - -// /// Creates frame result. -// fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { -// let mut env = Envcontext_interface::::default(); -// env.tx.gas_limit = 100; - -// let mut context = Context::builder(); -// context.evm.inner.env = Box::new(env); -// let mut first_frame = FrameResult::Call(CallOutcome::new( -// InterpreterResult { -// result: instruction_result, -// output: Bytes::new(), -// gas, -// }, -// 0..0, -// )); -// last_frame_return::(&mut context, &mut first_frame).unwrap(); -// refund::(&mut context, first_frame.gas_mut(), 0); -// *first_frame.gas() -// } - -// #[test] -// fn test_consume_gas() { -// let gas = call_last_frame_return(InstructionResult::Stop, Gas::new(90)); -// assert_eq!(gas.remaining(), 90); -// assert_eq!(gas.spent(), 10); -// assert_eq!(gas.refunded(), 0); -// } - -// #[test] -// fn test_consume_gas_with_refund() { -// let mut return_gas = Gas::new(90); -// return_gas.record_refund(30); - -// let gas = call_last_frame_return(InstructionResult::Stop, return_gas); -// assert_eq!(gas.remaining(), 90); -// assert_eq!(gas.spent(), 10); -// assert_eq!(gas.refunded(), 2); - -// let gas = call_last_frame_return(InstructionResult::Revert, return_gas); -// assert_eq!(gas.remaining(), 90); -// assert_eq!(gas.spent(), 10); -// assert_eq!(gas.refunded(), 0); -// } - -// #[test] -// fn test_revert_gas() { -// let gas = call_last_frame_return(InstructionResult::Revert, Gas::new(90)); -// assert_eq!(gas.remaining(), 90); -// assert_eq!(gas.spent(), 10); -// assert_eq!(gas.refunded(), 0); -// } -// } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index bc82401937..3d15e7ba21 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -6,10 +6,10 @@ use context_interface::{ TransactionGetter, }; use core::{cell::RefCell, cmp::min}; -use handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}; +use handler_interface::{Frame, ItemOrResult, PrecompileProvider, PrecompileProviderGetter}; use interpreter::{ gas, - interpreter::{EthInterpreter, ExtBytecode, InstructionProvider}, + interpreter::{EthInterpreter, ExtBytecode, InstructionProvider, InstructionProviderGetter}, interpreter_types::{LoopControl, ReturnData, RuntimeFlag}, return_ok, return_revert, CallInputs, CallOutcome, CallValue, CreateInputs, CreateOutcome, CreateScheme, EOFCreateInputs, EOFCreateKind, FrameInput, Gas, Host, InputsImpl, @@ -26,24 +26,20 @@ use state::Bytecode; use std::borrow::ToOwned; use std::{rc::Rc, sync::Arc}; -pub struct EthFrame { - _phantom: core::marker::PhantomData (CTX, ERROR)>, +pub struct EthFrame { + _phantom: core::marker::PhantomData<(FRAMECTX, CTX, ERROR)>, data: FrameData, - // TODO : Include this + /// Depth of the call frame. depth: usize, /// Journal checkpoint. pub checkpoint: JournalCheckpoint, /// Interpreter. pub interpreter: Interpreter, - /// Precompiles provider. - pub precompiles: PRECOMPILE, - /// Instruction provider. - pub instructions: INSTRUCTIONS, // This is worth making as a generic type FrameSharedContext. pub memory: Rc>, } -impl EthFrame +impl EthFrame where CTX: JournalGetter, IW: InterpreterTypes, @@ -53,8 +49,6 @@ where depth: usize, interpreter: Interpreter, checkpoint: JournalCheckpoint, - precompiles: PRECOMP, - instructions: INST, memory: Rc>, ) -> Self { Self { @@ -63,34 +57,38 @@ where depth, interpreter, checkpoint, - precompiles, - instructions, memory, } } } -impl - EthFrame, PRECOMPILE, INSTRUCTION> +impl EthFrame, FRAMECTX> where CTX: EthFrameContext, - ERROR: EthFrameError, - PRECOMPILE: PrecompileProvider, + ERROR: From> + From, + FRAMECTX: PrecompileProviderGetter< + PrecompileProvider: PrecompileProvider< + Context = CTX, + Error = ERROR, + Output = InterpreterResult, + >, + > + InstructionProviderGetter< + InstructionProvider: InstructionProvider, Host = CTX>, + >, { /// Make call frame #[inline] pub fn make_call_frame( context: &mut CTX, + frame_context: &mut FRAMECTX, depth: usize, memory: Rc>, inputs: &CallInputs, - mut precompile: PRECOMPILE, - instructions: INSTRUCTION, - ) -> Result, ERROR> { + ) -> Result, ERROR> { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { - Ok(FrameOrResultGen::Result(FrameResult::Call(CallOutcome { + Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { result: InterpreterResult { result: instruction_result, gas, @@ -128,7 +126,7 @@ where } let is_ext_delegate_call = inputs.scheme.is_ext_delegate_call(); if !is_ext_delegate_call { - if let Some(result) = precompile.run( + if let Some(result) = frame_context.precompiles().run( context, &inputs.bytecode_address, &inputs.input, @@ -139,7 +137,7 @@ where } else { context.journal().checkpoint_revert(checkpoint); } - return Ok(FrameOrResultGen::Result(FrameResult::Call(CallOutcome { + return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { result, memory_offset: inputs.return_memory_offset.clone(), }))); @@ -180,7 +178,7 @@ where call_value: inputs.value.get(), }; - Ok(FrameOrResultGen::Frame(Self::new( + Ok(ItemOrResult::Item(Self::new( FrameData::Call(CallFrame { return_memory_range: inputs.return_memory_offset.clone(), }), @@ -195,8 +193,6 @@ where inputs.gas_limit, ), checkpoint, - precompile, - instructions, memory, ))) } @@ -208,21 +204,17 @@ where depth: usize, memory: Rc>, inputs: &CreateInputs, - precompile: PRECOMPILE, - instructions: INSTRUCTION, - ) -> Result, ERROR> { + ) -> Result, ERROR> { let spec = context.cfg().spec().into(); let return_error = |e| { - Ok(FrameOrResultGen::Result(FrameResult::Create( - CreateOutcome { - result: InterpreterResult { - result: e, - gas: Gas::new(inputs.gas_limit), - output: Bytes::new(), - }, - address: None, + Ok(ItemOrResult::Result(FrameResult::Create(CreateOutcome { + result: InterpreterResult { + result: e, + gas: Gas::new(inputs.gas_limit), + output: Bytes::new(), }, - ))) + address: None, + }))) }; // Check depth @@ -255,13 +247,12 @@ where } // Create address - // TODO : Incorporating code hash inside interpreter. It was a request by foundry. - let mut _init_code_hash = B256::ZERO; + let mut init_code_hash = B256::ZERO; let created_address = match inputs.scheme { CreateScheme::Create => inputs.caller.create(old_nonce), CreateScheme::Create2 { salt } => { - _init_code_hash = keccak256(&inputs.init_code); - inputs.caller.create2(salt.to_be_bytes(), _init_code_hash) + init_code_hash = keccak256(&inputs.init_code); + inputs.caller.create2(salt.to_be_bytes(), init_code_hash) } }; @@ -279,7 +270,10 @@ where Err(e) => return return_error(e.into()), }; - let bytecode = ExtBytecode::new(Bytecode::new_legacy(inputs.init_code.clone())); + let bytecode = ExtBytecode::new_with_hash( + Bytecode::new_legacy(inputs.init_code.clone()), + init_code_hash, + ); let interpreter_input = InputsImpl { target_address: created_address, @@ -288,7 +282,7 @@ where call_value: inputs.value, }; - Ok(FrameOrResultGen::Frame(Self::new( + Ok(ItemOrResult::Item(Self::new( FrameData::Create(CreateFrame { created_address }), depth, Interpreter::new( @@ -301,8 +295,6 @@ where inputs.gas_limit, ), checkpoint, - precompile, - instructions, memory, ))) } @@ -314,12 +306,10 @@ where depth: usize, memory: Rc>, inputs: &EOFCreateInputs, - precompile: PRECOMPILE, - instructions: INSTRUCTION, - ) -> Result, ERROR> { + ) -> Result, ERROR> { let spec = context.cfg().spec().into(); let return_error = |e| { - Ok(FrameOrResultGen::Result(FrameResult::EOFCreate( + Ok(ItemOrResult::Result(FrameResult::EOFCreate( CreateOutcome { result: InterpreterResult { result: e, @@ -405,7 +395,7 @@ where call_value: inputs.value, }; - Ok(FrameOrResultGen::Frame(Self::new( + Ok(ItemOrResult::Item(Self::new( FrameData::EOFCreate(EOFCreateFrame { created_address }), depth, Interpreter::new( @@ -418,8 +408,6 @@ where inputs.gas_limit, ), checkpoint, - precompile, - instructions, memory, ))) } @@ -428,61 +416,96 @@ where depth: usize, frame_init: FrameInput, memory: Rc>, - precompile: PRECOMPILE, - instructions: INSTRUCTION, context: &mut CTX, - ) -> Result, ERROR> { + frame_context: &mut FRAMECTX, + ) -> Result, ERROR> { match frame_init { FrameInput::Call(inputs) => { - Self::make_call_frame(context, depth, memory, &inputs, precompile, instructions) + Self::make_call_frame(context, frame_context, depth, memory, &inputs) } - FrameInput::Create(inputs) => { - Self::make_create_frame(context, depth, memory, &inputs, precompile, instructions) + FrameInput::Create(inputs) => Self::make_create_frame(context, depth, memory, &inputs), + FrameInput::EOFCreate(inputs) => { + Self::make_eofcreate_frame(context, depth, memory, &inputs) } - FrameInput::EOFCreate(inputs) => Self::make_eofcreate_frame( - context, - depth, - memory, - &inputs, - precompile, - instructions, - ), } } } -impl Frame - for EthFrame, PRECOMPILE, INSTRUCTION> +pub struct FrameContext { + pub precompiles: PRECOMPILE, + pub instructions: INSTRUCTION, +} + +impl + FrameContext +{ + pub fn new(precompiles: PRECOMPILE, instructions: INSTRUCTION) -> Self { + Self { + precompiles, + instructions, + } + } +} + +impl PrecompileProviderGetter + for FrameContext +{ + type PrecompileProvider = PRECOMPILES; + + fn precompiles(&mut self) -> &mut Self::PrecompileProvider { + &mut self.precompiles + } +} + +impl InstructionProviderGetter + for FrameContext +{ + type InstructionProvider = INSTRUCTIONS; + + fn instructions(&mut self) -> &mut Self::InstructionProvider { + &mut self.instructions + } +} + +impl Frame for EthFrame, FRAMECTX> where CTX: EthFrameContext, - ERROR: EthFrameError, - PRECOMPILE: PrecompileProvider, - INSTRUCTION: InstructionProvider, Host = CTX>, + ERROR: From> + From, + FRAMECTX: PrecompileProviderGetter< + PrecompileProvider: PrecompileProvider< + Context = CTX, + Error = ERROR, + Output = InterpreterResult, + >, + > + InstructionProviderGetter< + InstructionProvider: InstructionProvider, Host = CTX>, + >, { type Context = CTX; type Error = ERROR; type FrameInit = FrameInput; + type FrameContext = FRAMECTX; type FrameResult = FrameResult; fn init_first( context: &mut Self::Context, + frame_context: &mut Self::FrameContext, frame_input: Self::FrameInit, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let memory = Rc::new(RefCell::new(SharedMemory::new())); - let precompiles = PRECOMPILE::new(context); - let instructions = INSTRUCTION::new(context); // Load precompiles addresses as warm. - for address in precompiles.warm_addresses() { + for address in frame_context.precompiles().warm_addresses() { context.journal().warm_account(address); } memory.borrow_mut().new_context(); - Self::init_with_context(0, frame_input, memory, precompiles, instructions, context) + Self::init_with_context(0, frame_input, memory, context, frame_context) } fn final_return( _context: &mut Self::Context, + _frame_context: &mut Self::FrameContext, _result: &mut Self::FrameResult, ) -> Result<(), Self::Error> { Ok(()) @@ -491,32 +514,33 @@ where fn init( &self, context: &mut CTX, + frame_context: &mut Self::FrameContext, frame_init: Self::FrameInit, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.memory.borrow_mut().new_context(); Self::init_with_context( self.depth + 1, frame_init, self.memory.clone(), - self.precompiles.clone(), - self.instructions.clone(), context, + frame_context, ) } fn run( &mut self, context: &mut Self::Context, - ) -> Result, Self::Error> { + frame_context: &mut Self::FrameContext, + ) -> Result, Self::Error> { let spec = context.cfg().spec().into(); // Run interpreter - let next_action = self.interpreter.run(self.instructions.table(), context); + let next_action = self + .interpreter + .run(frame_context.instructions().table(), context); let mut interpreter_result = match next_action { - InterpreterAction::NewFrame(new_frame) => { - return Ok(FrameOrResultGen::Frame(new_frame)) - } + InterpreterAction::NewFrame(new_frame) => return Ok(ItemOrResult::Item(new_frame)), InterpreterAction::Return { result } => result, InterpreterAction::None => unreachable!("InterpreterAction::None is not expected"), }; @@ -531,7 +555,7 @@ where } else { context.journal().checkpoint_revert(self.checkpoint); } - FrameOrResultGen::Result(FrameResult::Call(CallOutcome::new( + ItemOrResult::Result(FrameResult::Call(CallOutcome::new( interpreter_result, frame.return_memory_range.clone(), ))) @@ -547,7 +571,7 @@ where spec, ); - FrameOrResultGen::Result(FrameResult::Create(CreateOutcome::new( + ItemOrResult::Result(FrameResult::Create(CreateOutcome::new( interpreter_result, Some(frame.created_address), ))) @@ -562,7 +586,7 @@ where max_code_size, ); - FrameOrResultGen::Result(FrameResult::EOFCreate(CreateOutcome::new( + ItemOrResult::Result(FrameResult::EOFCreate(CreateOutcome::new( interpreter_result, Some(frame.created_address), ))) @@ -575,6 +599,7 @@ where fn return_result( &mut self, context: &mut Self::Context, + _frame_context: &mut Self::FrameContext, result: Self::FrameResult, ) -> Result<(), Self::Error> { self.memory.borrow_mut().free_context(); @@ -816,13 +841,3 @@ impl< > EthFrameContext for CTX { } - -pub trait EthFrameError: - From> + From -{ -} - -impl> + From> EthFrameError - for T -{ -} diff --git a/crates/handler/src/frame_data.rs b/crates/handler/src/frame_data.rs index 3e0f193bf8..3b36cbf7e4 100644 --- a/crates/handler/src/frame_data.rs +++ b/crates/handler/src/frame_data.rs @@ -4,24 +4,24 @@ use interpreter::{CallOutcome, CreateOutcome, Gas, InstructionResult, Interprete use primitives::Address; /// Call Frame -//#[derive(Debug)] -//#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CallFrame { /// Call frame has return memory range where output will be stored. pub return_memory_range: Range, } /// Create Frame -//#[derive(Debug)] -//#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateFrame { /// Create frame has a created address. pub created_address: Address, } /// Eof Create Frame -//#[derive(Debug)] -//#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EOFCreateFrame { pub created_address: Address, } @@ -29,8 +29,8 @@ pub struct EOFCreateFrame { /// Frame Data /// /// [`FrameData`] bundles different types of frames. -//#[derive(Debug)] -//#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FrameData { Call(CallFrame), Create(CreateFrame), diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs new file mode 100644 index 0000000000..fa8103c9b6 --- /dev/null +++ b/crates/handler/src/handler.rs @@ -0,0 +1,313 @@ +pub mod types; + +pub use types::{EthContext, EthError, EthHandlerImpl}; + +use crate::{execution, post_execution, pre_execution, validation, FrameContext, FrameResult}; +use context_interface::{ + result::{HaltReasonTrait, ResultAndState}, + Cfg, CfgGetter, ErrorGetter, Journal, JournalGetter, Transaction, TransactionGetter, +}; +use handler_interface::{ + Frame, FrameInitOrResult, FrameOrResult, ItemOrResult, PrecompileProvider, +}; +use interpreter::{interpreter::InstructionProvider, FrameInput, InitialAndFloorGas}; +use std::{vec, vec::Vec}; + +pub trait EthHandler { + type Context: EthContext; + type Error: EthError; + type Precompiles: PrecompileProvider; + type Instructions: InstructionProvider; + // TODO `FrameResult` should be a generic trait. + // TODO `FrameInit` should be a generic. + type Frame: Frame< + Context = Self::Context, + Error = Self::Error, + FrameResult = FrameResult, + FrameInit = FrameInput, + FrameContext = FrameContext, + >; + // TODO `HaltReason` should be a ExecResult trait, returned by the handler. + type HaltReason: HaltReasonTrait; + + fn run( + &mut self, + context: &mut Self::Context, + ) -> Result, Self::Error> { + let init_and_floor_gas = self.validate(context)?; + let eip7702_refund = self.pre_execution(context)? as i64; + let exec_result = self.execution(context, &init_and_floor_gas)?; + self.post_execution(context, exec_result, init_and_floor_gas, eip7702_refund) + } + + fn frame_context( + &mut self, + context: &mut Self::Context, + ) -> ::FrameContext; + + /// Call all validation functions + fn validate(&self, context: &mut Self::Context) -> Result { + self.validate_env(context)?; + self.validate_tx_against_state(context)?; + self.validate_initial_tx_gas(context) + } + + /// Call all Pre execution functions. + fn pre_execution(&self, context: &mut Self::Context) -> Result { + self.load_accounts(context)?; + self.deduct_caller(context)?; + let gas = self.apply_eip7702_auth_list(context)?; + Ok(gas) + } + + fn execution( + &mut self, + context: &mut Self::Context, + init_and_floor_gas: &InitialAndFloorGas, + ) -> Result { + let gas_limit = context.tx().gas_limit() - init_and_floor_gas.initial_gas; + + // Make a context! + let mut frame_context = self.frame_context(context); + // Create first frame action + let first_frame = self.create_first_frame(context, &mut frame_context, gas_limit)?; + let mut frame_result = match first_frame { + ItemOrResult::Item(frame) => self.run_exec_loop(context, &mut frame_context, frame)?, + ItemOrResult::Result(result) => result, + }; + + self.last_frame_result(context, &mut frame_context, &mut frame_result)?; + Ok(frame_result) + } + + fn post_execution( + &self, + context: &mut Self::Context, + mut exec_result: FrameResult, + init_and_floor_gas: InitialAndFloorGas, + eip7702_gas_refund: i64, + ) -> Result, Self::Error> { + // Calculate final refund and add EIP-7702 refund to gas. + self.refund(context, &mut exec_result, eip7702_gas_refund); + // Check if gas floor is met and spent at least a floor gas. + self.eip7623_check_gas_floor(context, &mut exec_result, init_and_floor_gas); + // Reimburse the caller + self.reimburse_caller(context, &mut exec_result)?; + // Reward beneficiary + self.reward_beneficiary(context, &mut exec_result)?; + // Returns output of transaction. + self.output(context, exec_result) + } + + /* VALIDATION */ + + /// Validate env. + fn validate_env(&self, context: &Self::Context) -> Result<(), Self::Error> { + validation::validate_env(context) + } + + /// Validate transactions against state. + fn validate_tx_against_state(&self, context: &mut Self::Context) -> Result<(), Self::Error> { + validation::validate_tx_against_state(context) + } + + /// Validate initial gas. + fn validate_initial_tx_gas( + &self, + context: &Self::Context, + ) -> Result { + validation::validate_initial_tx_gas(context.tx(), context.cfg().spec().into()) + .map_err(From::from) + } + + /* PRE EXECUTION */ + + fn load_accounts(&self, context: &mut Self::Context) -> Result<(), Self::Error> { + pre_execution::load_accounts(context) + } + + fn apply_eip7702_auth_list(&self, context: &mut Self::Context) -> Result { + pre_execution::apply_eip7702_auth_list(context) + } + + fn deduct_caller(&self, context: &mut Self::Context) -> Result<(), Self::Error> { + pre_execution::deduct_caller(context).map_err(From::from) + } + + /* EXECUTION */ + fn create_first_frame( + &mut self, + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + gas_limit: u64, + ) -> Result, Self::Error> { + let init_frame = + execution::create_init_frame(context.tx(), context.cfg().spec().into(), gas_limit); + self.frame_init_first(context, frame_context, init_frame) + } + + fn last_frame_result( + &self, + context: &mut Self::Context, + _frame_context: &mut ::FrameContext, + frame_result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { + execution::last_frame_result(context, frame_result); + Ok(()) + } + + /* FRAMES */ + + fn frame_init_first( + &mut self, + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + frame_input: ::FrameInit, + ) -> Result, Self::Error> { + Self::Frame::init_first(context, frame_context, frame_input) + } + + fn frame_init( + &self, + frame: &Self::Frame, + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + frame_input: ::FrameInit, + ) -> Result, Self::Error> { + Frame::init(frame, context, frame_context, frame_input) + } + + fn frame_call( + &mut self, + frame: &mut Self::Frame, + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + ) -> Result, Self::Error> { + Frame::run(frame, context, frame_context) + } + + fn frame_return_result( + &mut self, + frame: &mut Self::Frame, + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + result: ::FrameResult, + ) -> Result<(), Self::Error> { + Self::Frame::return_result(frame, context, frame_context, result) + } + + fn frame_final_return( + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { + Self::Frame::final_return(context, frame_context, result)?; + Ok(()) + } + + fn run_exec_loop( + &self, + context: &mut Self::Context, + frame_context: &mut ::FrameContext, + frame: Self::Frame, + ) -> Result { + let mut frame_stack: Vec = vec![frame]; + loop { + let frame = frame_stack.last_mut().unwrap(); + let call_or_result = frame.run(context, frame_context)?; + + let mut result = match call_or_result { + ItemOrResult::Item(init) => match frame.init(context, frame_context, init)? { + ItemOrResult::Item(new_frame) => { + frame_stack.push(new_frame); + continue; + } + // Dont pop the frame as new frame was not created. + ItemOrResult::Result(result) => result, + }, + ItemOrResult::Result(result) => { + // Pop frame that returned result + frame_stack.pop(); + result + } + }; + + let Some(frame) = frame_stack.last_mut() else { + Self::Frame::final_return(context, frame_context, &mut result)?; + return Ok(result); + }; + frame.return_result(context, frame_context, result)?; + } + } + + /* POST EXECUTION */ + + /// Calculate final refund. + fn eip7623_check_gas_floor( + &self, + _context: &mut Self::Context, + exec_result: &mut ::FrameResult, + init_and_floor_gas: InitialAndFloorGas, + ) { + post_execution::eip7623_check_gas_floor(exec_result.gas_mut(), init_and_floor_gas) + } + + /// Calculate final refund. + fn refund( + &self, + context: &mut Self::Context, + exec_result: &mut ::FrameResult, + eip7702_refund: i64, + ) { + let spec = context.cfg().spec().into(); + post_execution::refund(spec, exec_result.gas_mut(), eip7702_refund) + } + + /// Reimburse the caller with balance it didn't spent. + fn reimburse_caller( + &self, + context: &mut Self::Context, + exec_result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { + post_execution::reimburse_caller(context, exec_result.gas_mut()).map_err(From::from) + } + + /// Reward beneficiary with transaction rewards. + fn reward_beneficiary( + &self, + context: &mut Self::Context, + exec_result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { + post_execution::reward_beneficiary(context, exec_result.gas_mut()).map_err(From::from) + } + + /// Main return handle, takes state from journal and transforms internal result to output. + fn output( + &self, + context: &mut Self::Context, + result: ::FrameResult, + ) -> Result, Self::Error> { + context.take_error()?; + Ok(post_execution::output(context, result)) + } + + /// Called when execution ends. + /// + /// End handle in comparison to output handle will be called every time after execution. + /// + /// While output will be omitted in case of the error. + fn end( + &self, + _context: &mut Self::Context, + end_output: Result, Self::Error>, + ) -> Result, Self::Error> { + end_output + } + + /// Clean handler. It resets internal Journal state to default one. + /// + /// This handle is called every time regardless of the result of the transaction. + fn clear(&self, context: &mut Self::Context) { + context.journal().clear(); + } +} diff --git a/crates/handler/src/handler/types.rs b/crates/handler/src/handler/types.rs new file mode 100644 index 0000000000..8ea7a68990 --- /dev/null +++ b/crates/handler/src/handler/types.rs @@ -0,0 +1,144 @@ +use context::Context; +use context_interface::{ + result::{HaltReason, InvalidHeader, InvalidTransaction}, + Block, BlockGetter, Cfg, CfgGetter, Database, DatabaseGetter, ErrorGetter, Journal, + JournalDBError, JournalGetter, PerformantContextAccess, Transaction, TransactionGetter, +}; +use handler_interface::{Frame, PrecompileProvider}; +use interpreter::{ + interpreter::{EthInstructionProvider, EthInterpreter, InstructionProvider}, + FrameInput, Host, +}; +use precompile::PrecompileErrors; +use primitives::Log; +use specification::hardfork::SpecId; +use state::EvmState; +use std::vec::Vec; + +use crate::{EthPrecompileProvider, FrameContext, FrameResult}; + +use super::EthHandler; + +pub struct EthHandlerImpl { + pub precompiles: PRECOMPILES, + pub instructions: INSTRUCTIONS, + pub _phantom: core::marker::PhantomData<(CTX, ERROR, FRAME, PRECOMPILES, INSTRUCTIONS)>, +} + +impl + EthHandlerImpl +where + PRECOMPILES: PrecompileProvider, + INSTRUCTIONS: InstructionProvider, +{ + pub fn crete_frame_context(&self) -> FrameContext { + FrameContext { + precompiles: self.precompiles.clone(), + instructions: self.instructions.clone(), + } + } +} + +impl EthHandler + for EthHandlerImpl +where + CTX: EthContext, + ERROR: EthError, + PRECOMPILES: PrecompileProvider< + Context = CTX, + Error = ERROR, + Spec = <::Cfg as Cfg>::Spec, + >, + INSTRUCTIONS: InstructionProvider, + // TODO `FrameResult` should be a generic trait. + // TODO `FrameInit` should be a generic. + FRAME: Frame< + Context = CTX, + Error = ERROR, + FrameResult = FrameResult, + FrameInit = FrameInput, + FrameContext = FrameContext, + >, +{ + type Context = CTX; + type Error = ERROR; + type Frame = FRAME; + type Precompiles = PRECOMPILES; + type Instructions = INSTRUCTIONS; + type HaltReason = HaltReason; + + fn frame_context( + &mut self, + context: &mut Self::Context, + ) -> ::FrameContext { + self.precompiles.set_spec(context.cfg().spec()); + self.crete_frame_context() + } +} + +impl Default + for EthHandlerImpl< + CTX, + ERROR, + FRAME, + EthPrecompileProvider, + EthInstructionProvider, + > +{ + fn default() -> Self { + Self { + precompiles: EthPrecompileProvider::new(SpecId::LATEST), + instructions: EthInstructionProvider::new(), + _phantom: core::marker::PhantomData, + } + } +} + +pub trait EthContext: + TransactionGetter + + BlockGetter + + DatabaseGetter + + CfgGetter + + PerformantContextAccess> + + ErrorGetter> + + JournalGetter)>> + + Host +{ +} + +pub trait EthError: + From + From + From> + From +{ +} + +impl< + CTX: JournalGetter, + T: From + + From + + From> + + From, + > EthError for T +{ +} + +impl< + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal)>, + CHAIN, + > EthContext for Context +{ +} + +impl< + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal)>, + CHAIN, + > EthContext for &mut Context +{ +} diff --git a/crates/handler/src/lib.rs b/crates/handler/src/lib.rs index f3a261fa73..bb7aae1987 100644 --- a/crates/handler/src/lib.rs +++ b/crates/handler/src/lib.rs @@ -7,132 +7,17 @@ extern crate alloc as std; // Mainnet related handlers. -mod execution; +pub mod execution; mod frame; mod frame_data; -mod post_execution; -mod pre_execution; +pub mod handler; +pub mod post_execution; +pub mod pre_execution; mod precompile_provider; -mod validation; +pub mod validation; // Public exports - -pub use execution::{EthExecution, EthExecutionContext, EthExecutionError}; -pub use frame::{return_create, return_eofcreate, EthFrame, EthFrameContext, EthFrameError}; +pub use frame::{return_create, return_eofcreate, EthFrame, EthFrameContext, FrameContext}; pub use frame_data::{FrameData, FrameResult}; -pub use post_execution::{EthPostExecution, EthPostExecutionContext, EthPostExecutionError}; -pub use pre_execution::{ - apply_eip7702_auth_list, EthPreExecution, EthPreExecutionContext, EthPreExecutionError, -}; -use precompile::PrecompileErrors; +pub use handler::{EthContext, EthError, EthHandler, EthHandlerImpl}; pub use precompile_provider::EthPrecompileProvider; -use primitives::Log; -use state::EvmState; -use std::vec::Vec; -pub use validation::{ - validate_eip4844_tx, validate_initial_tx_gas, validate_priority_fee_tx, - validate_tx_against_account, validate_tx_env, EthValidation, EthValidationContext, - EthValidationError, -}; - -// Imports - -use context_interface::{ - journaled_state::Journal, - result::{HaltReason, InvalidHeader, InvalidTransaction}, -}; -use context_interface::{ - BlockGetter, CfgGetter, ErrorGetter, JournalDBError, JournalGetter, TransactionGetter, -}; -use handler_interface::{ - ExecutionHandler, Handler, PostExecutionHandler, PreExecutionHandler, ValidationHandler, -}; -use interpreter::Host; - -#[derive(Default)] -pub struct EthHandler< - CTX, - ERROR, - VAL = EthValidation, - PREEXEC = EthPreExecution, - EXEC = EthExecution, - POSTEXEC = EthPostExecution, -> { - pub validation: VAL, - pub pre_execution: PREEXEC, - pub execution: EXEC, - pub post_execution: POSTEXEC, - _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 -{ - pub fn new( - validation: VAL, - pre_execution: PREEXEC, - execution: EXEC, - post_execution: POSTEXEC, - ) -> Self { - Self { - validation, - pre_execution, - execution, - post_execution, - _phantom: core::marker::PhantomData, - } - } -} - -impl Handler - for EthHandler -where - CTX: TransactionGetter - + BlockGetter - + JournalGetter - + CfgGetter - + ErrorGetter> - + JournalGetter)>> - + Host, - ERROR: From - + From - + From> - + From, - VAL: ValidationHandler, - PREEXEC: PreExecutionHandler, - EXEC: ExecutionHandler, - POSTEXEC: PostExecutionHandler, -{ - type Validation = VAL; - type PreExecution = PREEXEC; - type Execution = EXEC; - type PostExecution = POSTEXEC; - - fn validation(&mut self) -> &mut Self::Validation { - &mut self.validation - } - - fn pre_execution(&mut self) -> &mut Self::PreExecution { - &mut self.pre_execution - } - - fn execution(&mut self) -> &mut Self::Execution { - &mut self.execution - } - - fn post_execution(&mut self) -> &mut Self::PostExecution { - &mut self.post_execution - } -} diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index 9520a30455..7701d7b90c 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -1,214 +1,134 @@ +use super::frame_data::FrameResult; use context_interface::{ journaled_state::Journal, result::{ExecutionResult, HaltReasonTrait, ResultAndState}, - Block, BlockGetter, Cfg, CfgGetter, ErrorGetter, JournalDBError, JournalGetter, Transaction, + Block, BlockGetter, Cfg, CfgGetter, JournalDBError, JournalGetter, Transaction, TransactionGetter, }; -use handler_interface::PostExecutionHandler; -use interpreter::SuccessOrHalt; +use interpreter::{Gas, InitialAndFloorGas, SuccessOrHalt}; use primitives::{Log, U256}; use specification::hardfork::SpecId; use state::EvmState; -use std::{boxed::Box, vec::Vec}; - -use super::frame_data::FrameResult; - -#[derive(Default)] -pub struct EthPostExecution { - pub _phantom: core::marker::PhantomData<(CTX, ERROR, HALTREASON)>, -} - -impl EthPostExecution { - /// Create new instance of post execution handler. - pub fn new() -> Self { - Self { - _phantom: core::marker::PhantomData, - } - } - - /// Create new boxed instance of post execution handler. - /// - /// Boxed instance is useful to erase FORK type. - pub fn new_boxed() -> Box { - Box::new(Self::new()) +use std::vec::Vec; + +pub fn eip7623_check_gas_floor(gas: &mut Gas, init_and_floor_gas: InitialAndFloorGas) { + // EIP-7623: Increase calldata cost + // spend at least a gas_floor amount of gas. + if gas.spent_sub_refunded() < init_and_floor_gas.floor_gas { + gas.set_spent(init_and_floor_gas.floor_gas); + // clear refund + gas.set_refund(0); } } -impl PostExecutionHandler for EthPostExecution -where - CTX: EthPostExecutionContext, - ERROR: EthPostExecutionError, - HALTREASON: HaltReasonTrait, -{ - type Context = CTX; - type Error = ERROR; - type ExecResult = FrameResult; - type Output = ResultAndState; - - fn eip7623_check_gas_floor( - &self, - _context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - init_and_floor_gas: handler_interface::InitialAndFloorGas, - ) { - let gas = exec_result.gas_mut(); - // EIP-7623: Increase calldata cost - // spend at least a gas_floor amount of gas. - if gas.spent_sub_refunded() < init_and_floor_gas.floor_gas { - gas.set_spent(init_and_floor_gas.floor_gas); - // clear refund - gas.set_refund(0); - } - } - - fn refund( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - eip7702_refund: i64, - ) { - let gas = exec_result.gas_mut(); - gas.record_refund(eip7702_refund); - - // Calculate gas refund for transaction. - // If spec is set to london, it will decrease the maximum refund amount to 5th part of - // gas spend. (Before london it was 2th part of gas spend) - gas.set_final_refund(context.cfg().spec().into().is_enabled_in(SpecId::LONDON)); - } - - fn reimburse_caller( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error> { - let basefee = context.block().basefee() as u128; - let caller = context.tx().caller(); - let effective_gas_price = context.tx().effective_gas_price(basefee); - let gas = exec_result.gas(); +pub fn refund(spec: SpecId, gas: &mut Gas, eip7702_refund: i64) { + gas.record_refund(eip7702_refund); + // Calculate gas refund for transaction. + // If spec is set to london, it will decrease the maximum refund amount to 5th part of + // gas spend. (Before london it was 2th part of gas spend) + gas.set_final_refund(spec.is_enabled_in(SpecId::LONDON)); +} - // Return balance of not spend gas. - let caller_account = context.journal().load_account(caller)?; +pub fn reimburse_caller( + context: &mut CTX, + gas: &mut Gas, +) -> Result<(), JournalDBError> { + let basefee = context.block().basefee() as u128; + let caller = context.tx().caller(); + let effective_gas_price = context.tx().effective_gas_price(basefee); + + // Return balance of not spend gas. + let caller_account = context.journal().load_account(caller)?; + + let reimbursed = + effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128); + caller_account.data.info.balance = caller_account + .data + .info + .balance + .saturating_add(U256::from(reimbursed)); + + Ok(()) +} - let reimbursed = - effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128); - caller_account.data.info.balance = caller_account +pub fn reward_beneficiary( + context: &mut CTX, + gas: &mut Gas, +) -> Result<(), JournalDBError> { + let block = context.block(); + let tx = context.tx(); + let beneficiary = block.beneficiary(); + let basefee = block.basefee() as u128; + let effective_gas_price = tx.effective_gas_price(basefee); + + // Transfer fee to coinbase/beneficiary. + // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. + let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) { + effective_gas_price.saturating_sub(basefee) + } else { + effective_gas_price + }; + + let coinbase_account = context.journal().load_account(beneficiary)?; + + coinbase_account.data.mark_touch(); + coinbase_account.data.info.balance = + coinbase_account .data .info .balance - .saturating_add(U256::from(reimbursed)); + .saturating_add(U256::from( + coinbase_gas_price * (gas.spent() - gas.refunded() as u64) as u128, + )); - Ok(()) - } - - fn reward_beneficiary( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error> { - let block = context.block(); - let tx = context.tx(); - let beneficiary = block.beneficiary(); - let basefee = block.basefee() as u128; - let effective_gas_price = tx.effective_gas_price(basefee); - let gas = exec_result.gas(); - - // Transfer fee to coinbase/beneficiary. - // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. - let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) { - effective_gas_price.saturating_sub(basefee) - } else { - effective_gas_price - }; - - let coinbase_account = context.journal().load_account(beneficiary)?; - - coinbase_account.data.mark_touch(); - coinbase_account.data.info.balance = - coinbase_account - .data - .info - .balance - .saturating_add(U256::from( - coinbase_gas_price * (gas.spent() - gas.refunded() as u64) as u128, - )); - - Ok(()) - } - - fn output( - &self, - context: &mut Self::Context, - result: Self::ExecResult, - ) -> Result { - context.take_error()?; - - // Used gas with refund calculated. - let gas_refunded = result.gas().refunded() as u64; - let final_gas_used = result.gas().spent() - gas_refunded; - let output = result.output(); - let instruction_result = result.into_interpreter_result(); - - // Reset journal and return present state. - let (state, logs) = context.journal().finalize()?; - - let result = match SuccessOrHalt::::from(instruction_result.result) { - SuccessOrHalt::Success(reason) => ExecutionResult::Success { - reason, - gas_used: final_gas_used, - gas_refunded, - logs, - output, - }, - SuccessOrHalt::Revert => ExecutionResult::Revert { - gas_used: final_gas_used, - output: output.into_data(), - }, - SuccessOrHalt::Halt(reason) => ExecutionResult::Halt { - reason, - gas_used: final_gas_used, - }, - // Only two internal return flags. - flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => { - panic!( - "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", - flag, instruction_result - ) - } - }; - - Ok(ResultAndState { result, state }) - } - - fn clear(&self, context: &mut Self::Context) { - // Clear error and journaled state. - // TODO : Check effects of removal of take_error - // let _ = context.evm.take_error(); - context.journal().clear(); - } + Ok(()) } -/// Trait for post execution context. +/// Calculate last gas spent and transform internal reason to external. /// -// TODO : Generalize FinalOutput. -pub trait EthPostExecutionContext: - TransactionGetter - + ErrorGetter> - + BlockGetter - + JournalGetter)>> - + CfgGetter -{ -} +/// TODO make Journal FinalOutput more generic. +pub fn output< + CTX: JournalGetter)>>, + HALTREASON: HaltReasonTrait, +>( + context: &mut CTX, + // TODO, make this more generic and nice. + // FrameResult should be a generic that returns gas and interpreter result. + result: FrameResult, +) -> ResultAndState { + // Used gas with refund calculated. + let gas_refunded = result.gas().refunded() as u64; + let final_gas_used = result.gas().spent() - gas_refunded; + let output = result.output(); + let instruction_result = result.into_interpreter_result(); + + // Reset journal and return present state. + let (state, logs) = context.journal().finalize(); + + let result = match SuccessOrHalt::::from(instruction_result.result) { + SuccessOrHalt::Success(reason) => ExecutionResult::Success { + reason, + gas_used: final_gas_used, + gas_refunded, + logs, + output, + }, + SuccessOrHalt::Revert => ExecutionResult::Revert { + gas_used: final_gas_used, + output: output.into_data(), + }, + SuccessOrHalt::Halt(reason) => ExecutionResult::Halt { + reason, + gas_used: final_gas_used, + }, + // Only two internal return flags. + flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => { + panic!( + "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", + flag, instruction_result + ) + } + }; -impl< - CTX: TransactionGetter - + ErrorGetter> - + BlockGetter - + JournalGetter)>> - + CfgGetter, - > EthPostExecutionContext for CTX -{ + ResultAndState { result, state } } - -pub trait EthPostExecutionError: From> {} - -impl>> EthPostExecutionError for ERROR {} diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 857ddf3dfc..fe6bde7538 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -10,105 +10,76 @@ use context_interface::{ Block, BlockGetter, Cfg, CfgGetter, Database, DatabaseGetter, JournalDBError, JournalGetter, PerformantContextAccess, TransactionGetter, }; -use handler_interface::PreExecutionHandler; use primitives::{Address, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256}; use specification::{eip7702, hardfork::SpecId}; -use std::{boxed::Box, vec::Vec}; +use std::vec::Vec; -#[derive(Default)] -pub struct EthPreExecution { - pub _phantom: core::marker::PhantomData<(CTX, ERROR)>, -} - -impl EthPreExecution { - pub fn new() -> Self { - Self { - _phantom: core::marker::PhantomData, - } +pub fn load_accounts< + CTX: PerformantContextAccess + BlockGetter + JournalGetter + CfgGetter, + ERROR: From> + From<::Error>, +>( + context: &mut CTX, +) -> Result<(), ERROR> { + let spec = context.cfg().spec().into(); + // Set journaling state flag. + context.journal().set_spec_id(spec); + + // 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().warm_account(coinbase); } - pub fn new_boxed() -> Box { - Box::new(Self::new()) + // Load blockhash storage address + // EIP-2935: Serve historical block hashes from state + if spec.is_enabled_in(SpecId::PRAGUE) { + context.journal().warm_account(BLOCKHASH_STORAGE_ADDRESS); } -} -impl PreExecutionHandler for EthPreExecution -where - CTX: EthPreExecutionContext, - ERROR: EthPreExecutionError, -{ - type Context = CTX; - type Error = ERROR; - - fn load_accounts(&self, context: &mut Self::Context) -> Result<(), Self::Error> { - let spec = context.cfg().spec().into(); - // Set journaling state flag. - context.journal().set_spec_id(spec); - - // 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().warm_account(coinbase); - } + // Load access list + context.load_access_list()?; - // Load blockhash storage address - // EIP-2935: Serve historical block hashes from state - if spec.is_enabled_in(SpecId::PRAGUE) { - context.journal().warm_account(BLOCKHASH_STORAGE_ADDRESS); - } - - // Load access list - context.load_access_list()?; + Ok(()) +} - Ok(()) +#[inline] +pub fn deduct_caller( + context: &mut CTX, +) -> Result<(), JournalDBError> { + let basefee = context.block().basefee(); + let blob_price = context.block().blob_gasprice().unwrap_or_default(); + let effective_gas_price = context.tx().effective_gas_price(basefee as u128); + // Subtract gas costs from the caller's account. + // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. + let mut gas_cost = (context.tx().gas_limit() as u128).saturating_mul(effective_gas_price); + + // EIP-4844 + if context.tx().tx_type() == TransactionType::Eip4844 { + let blob_gas = context.tx().total_blob_gas() as u128; + gas_cost = gas_cost.saturating_add(blob_price.saturating_mul(blob_gas)); } - fn apply_eip7702_auth_list(&self, context: &mut Self::Context) -> Result { - let spec = context.cfg().spec().into(); - if spec.is_enabled_in(SpecId::PRAGUE) { - apply_eip7702_auth_list::(context) - } else { - Ok(0) - } + let is_call = context.tx().kind().is_call(); + let caller = context.tx().caller(); + + // Load caller's account. + let caller_account = context.journal().load_account(caller)?.data; + // Set new caller account balance. + caller_account.info.balance = caller_account + .info + .balance + .saturating_sub(U256::from(gas_cost)); + + // Bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. + if is_call { + // Nonce is already checked + caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } - #[inline] - fn deduct_caller(&self, context: &mut Self::Context) -> Result<(), Self::Error> { - let basefee = context.block().basefee(); - let blob_price = context.block().blob_gasprice().unwrap_or_default(); - let effective_gas_price = context.tx().effective_gas_price(basefee as u128); - // Subtract gas costs from the caller's account. - // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. - let mut gas_cost = (context.tx().gas_limit() as u128).saturating_mul(effective_gas_price); - - // EIP-4844 - if context.tx().tx_type() == TransactionType::Eip4844 { - let blob_gas = context.tx().total_blob_gas() as u128; - gas_cost = gas_cost.saturating_add(blob_price.saturating_mul(blob_gas)); - } - - let is_call = context.tx().kind().is_call(); - let caller = context.tx().caller(); - - // Load caller's account. - let caller_account = context.journal().load_account(caller)?.data; - // Set new caller account balance. - caller_account.info.balance = caller_account - .info - .balance - .saturating_sub(U256::from(gas_cost)); - - // Bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. - if is_call { - // Nonce is already checked - caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); - } - - // Touch account so we know it is changed. - caller_account.mark_touch(); - Ok(()) - } + // Touch account so we know it is changed. + caller_account.mark_touch(); + Ok(()) } /// Apply EIP-7702 auth list and return number gas refund on already created accounts. @@ -119,12 +90,17 @@ pub fn apply_eip7702_auth_list< >( context: &mut CTX, ) -> Result { - // Return if there is no auth list. + let spec = context.cfg().spec().into(); let tx = context.tx(); + if !spec.is_enabled_in(SpecId::PRAGUE) { + return Ok(0); + } + // Return if there is no auth list. if tx.tx_type() != TransactionType::Eip7702 { return Ok(0); } + #[derive(Debug)] struct Authorization { authority: Option
, address: Address, @@ -225,13 +201,3 @@ impl< > EthPreExecutionContext for CTX { } - -pub trait EthPreExecutionError: - From + From> -{ -} - -impl + From>> - EthPreExecutionError for T -{ -} diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index 9fcbe764f0..a61ad97927 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -1,9 +1,12 @@ -use context_interface::{Cfg, CfgGetter}; +use context::Cfg; +use context_interface::CfgGetter; use handler_interface::PrecompileProvider; use interpreter::{Gas, InstructionResult, InterpreterResult}; use precompile::PrecompileErrors; use precompile::{PrecompileSpecId, Precompiles}; use primitives::{Address, Bytes}; +use specification::hardfork::SpecId; +use std::boxed::Box; pub struct EthPrecompileProvider { pub precompiles: &'static Precompiles, @@ -19,6 +22,15 @@ impl Clone for EthPrecompileProvider { } } +impl EthPrecompileProvider { + pub fn new(spec: SpecId) -> Self { + Self { + precompiles: Precompiles::new(PrecompileSpecId::from_spec_id(spec)), + _phantom: core::marker::PhantomData, + } + } +} + impl PrecompileProvider for EthPrecompileProvider where CTX: CfgGetter, @@ -27,13 +39,10 @@ where type Context = CTX; type Error = ERROR; type Output = InterpreterResult; + type Spec = <::Cfg as Cfg>::Spec; - fn new(context: &mut Self::Context) -> Self { - let spec = context.cfg().spec().into(); - Self { - precompiles: Precompiles::new(PrecompileSpecId::from_spec_id(spec)), - _phantom: core::marker::PhantomData, - } + fn set_spec(&mut self, spec: Self::Spec) { + self.precompiles = Precompiles::new(PrecompileSpecId::from_spec_id(spec.into())); } fn run( @@ -72,8 +81,8 @@ where Ok(Some(result)) } - fn warm_addresses(&self) -> impl Iterator { - self.precompiles.addresses().cloned() + fn warm_addresses(&self) -> Box> { + Box::new(self.precompiles.addresses().cloned()) } fn contains(&self, address: &Address) -> bool { diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index cd6498f1a7..420528cc3a 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -5,77 +5,44 @@ use context_interface::{ Block, BlockGetter, Cfg, CfgGetter, JournalDBError, JournalGetter, TransactionGetter, }; use core::cmp::{self, Ordering}; -use handler_interface::{InitialAndFloorGas, ValidationHandler}; -use interpreter::gas::{self}; +use interpreter::gas::{self, InitialAndFloorGas}; use primitives::{B256, U256}; use specification::{eip4844, hardfork::SpecId}; -use state::Account; +use state::AccountInfo; use std::boxed::Box; -pub struct EthValidation { - pub _phantom: core::marker::PhantomData (CTX, ERROR)>, -} - -impl Default for EthValidation { - fn default() -> Self { - Self { - _phantom: core::marker::PhantomData, - } - } -} - -impl EthValidation { - pub fn new() -> Self { - Self { - _phantom: core::marker::PhantomData, - } +pub fn validate_env< + CTX: CfgGetter + BlockGetter + TransactionGetter, + ERROR: From + From, +>( + context: CTX, +) -> Result<(), ERROR> { + let spec = context.cfg().spec().into(); + // `prevrandao` is required for the merge + if spec.is_enabled_in(SpecId::MERGE) && context.block().prevrandao().is_none() { + return Err(InvalidHeader::PrevrandaoNotSet.into()); } - - pub fn new_boxed() -> Box { - Box::new(Self::new()) + // `excess_blob_gas` is required for Cancun + if spec.is_enabled_in(SpecId::CANCUN) && context.block().blob_excess_gas_and_price().is_none() { + return Err(InvalidHeader::ExcessBlobGasNotSet.into()); } + validate_tx_env::(context, spec).map_err(Into::into) } -impl ValidationHandler for EthValidation -where - CTX: EthValidationContext, - ERROR: From + From + From>, -{ - type Context = CTX; - type Error = ERROR; - - fn validate_env(&self, context: &Self::Context) -> Result<(), Self::Error> { - let spec = context.cfg().spec().into(); - // `prevrandao` is required for the merge - if spec.is_enabled_in(SpecId::MERGE) && context.block().prevrandao().is_none() { - return Err(InvalidHeader::PrevrandaoNotSet.into()); - } - // `excess_blob_gas` is required for Cancun - if spec.is_enabled_in(SpecId::CANCUN) - && context.block().blob_excess_gas_and_price().is_none() - { - return Err(InvalidHeader::ExcessBlobGasNotSet.into()); - } - validate_tx_env::<&Self::Context, InvalidTransaction>(context, spec).map_err(Into::into) - } - - fn validate_tx_against_state(&self, context: &mut Self::Context) -> Result<(), Self::Error> { - let tx_caller = context.tx().caller(); +pub fn validate_tx_against_state< + CTX: TransactionGetter + JournalGetter + CfgGetter, + ERROR: From + From>, +>( + mut context: CTX, +) -> Result<(), ERROR> { + let tx_caller = context.tx().caller(); - // Load acc - let account = &mut context.journal().load_account_code(tx_caller)?; - let account = account.data.clone(); + // Load acc + let account = context.journal().load_account_code(tx_caller)?; + let account = account.data.info.clone(); - validate_tx_against_account::(&account, context) - } - - fn validate_initial_tx_gas( - &self, - context: &Self::Context, - ) -> Result { - let spec = context.cfg().spec().into(); - validate_initial_tx_gas(context.tx(), spec).map_err(From::from) - } + validate_tx_against_account::(&account, context)?; + Ok(()) } /// Validate transaction that has EIP-1559 priority fee @@ -139,10 +106,7 @@ pub fn validate_eip4844_tx( pub fn validate_tx_env( context: CTX, spec_id: SpecId, -) -> Result<(), Error> -where - Error: From, -{ +) -> Result<(), InvalidTransaction> { // Check if the transaction's chain id is correct let tx_type = context.tx().tx_type(); let tx = context.tx(); @@ -159,40 +123,40 @@ where // EIP-155: Simple replay attack protection if let Some(chain_id) = tx.chain_id() { if chain_id != context.cfg().chain_id() { - return Err(InvalidTransaction::InvalidChainId.into()); + return Err(InvalidTransaction::InvalidChainId); } } // Gas price must be at least the basefee. if let Some(base_fee) = base_fee { if tx.gas_price() < base_fee { - return Err(InvalidTransaction::GasPriceLessThanBasefee.into()); + return Err(InvalidTransaction::GasPriceLessThanBasefee); } } } TransactionType::Eip2930 => { // Enabled in BERLIN hardfork if !spec_id.is_enabled_in(SpecId::BERLIN) { - return Err(InvalidTransaction::Eip2930NotSupported.into()); + return Err(InvalidTransaction::Eip2930NotSupported); } if Some(context.cfg().chain_id()) != tx.chain_id() { - return Err(InvalidTransaction::InvalidChainId.into()); + return Err(InvalidTransaction::InvalidChainId); } // Gas price must be at least the basefee. if let Some(base_fee) = base_fee { if tx.gas_price() < base_fee { - return Err(InvalidTransaction::GasPriceLessThanBasefee.into()); + return Err(InvalidTransaction::GasPriceLessThanBasefee); } } } TransactionType::Eip1559 => { if !spec_id.is_enabled_in(SpecId::LONDON) { - return Err(InvalidTransaction::Eip1559NotSupported.into()); + return Err(InvalidTransaction::Eip1559NotSupported); } if Some(context.cfg().chain_id()) != tx.chain_id() { - return Err(InvalidTransaction::InvalidChainId.into()); + return Err(InvalidTransaction::InvalidChainId); } validate_priority_fee_tx( @@ -203,11 +167,11 @@ where } TransactionType::Eip4844 => { if !spec_id.is_enabled_in(SpecId::CANCUN) { - return Err(InvalidTransaction::Eip4844NotSupported.into()); + return Err(InvalidTransaction::Eip4844NotSupported); } if Some(context.cfg().chain_id()) != tx.chain_id() { - return Err(InvalidTransaction::InvalidChainId.into()); + return Err(InvalidTransaction::InvalidChainId); } validate_priority_fee_tx( @@ -226,11 +190,11 @@ where TransactionType::Eip7702 => { // Check if EIP-7702 transaction is enabled. if !spec_id.is_enabled_in(SpecId::PRAGUE) { - return Err(InvalidTransaction::Eip7702NotSupported.into()); + return Err(InvalidTransaction::Eip7702NotSupported); } if Some(context.cfg().chain_id()) != tx.chain_id() { - return Err(InvalidTransaction::InvalidChainId.into()); + return Err(InvalidTransaction::InvalidChainId); } validate_priority_fee_tx( @@ -242,7 +206,7 @@ where let auth_list_len = tx.authorization_list_len(); // The transaction is considered invalid if the length of authorization_list is zero. if auth_list_len == 0 { - return Err(InvalidTransaction::EmptyAuthorizationList.into()); + return Err(InvalidTransaction::EmptyAuthorizationList); } } TransactionType::Custom => { @@ -253,14 +217,14 @@ where // Check if gas_limit is more than block_gas_limit if !context.cfg().is_block_gas_limit_disabled() && tx.gas_limit() > context.block().gas_limit() { - return Err(InvalidTransaction::CallerGasLimitMoreThanBlock.into()); + return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); } // EIP-3860: Limit and meter initcode if spec_id.is_enabled_in(SpecId::SHANGHAI) && tx.kind().is_create() { let max_initcode_size = context.cfg().max_code_size().saturating_mul(2); if context.tx().input().len() > max_initcode_size { - return Err(InvalidTransaction::CreateInitCodeSizeLimit.into()); + return Err(InvalidTransaction::CreateInitCodeSizeLimit); } } @@ -269,37 +233,34 @@ where /// Validate account against the transaction. #[inline] -pub fn validate_tx_against_account( - account: &Account, - context: &CTX, -) -> Result<(), ERROR> -where - ERROR: From, -{ +pub fn validate_tx_against_account( + account: &AccountInfo, + context: CTX, +) -> Result<(), InvalidTransaction> { let tx = context.tx(); let tx_type = context.tx().tx_type(); // EIP-3607: Reject transactions from senders with deployed code // This EIP is introduced after london but there was no collision in past // so we can leave it enabled always if !context.cfg().is_eip3607_disabled() { - let bytecode = &account.info.code.as_ref().unwrap(); + let bytecode = &account.code.as_ref().unwrap(); // Allow EOAs whose code is a valid delegation designation, // i.e. 0xef0100 || address, to continue to originate transactions. if !bytecode.is_empty() && !bytecode.is_eip7702() { - return Err(InvalidTransaction::RejectCallerWithCode.into()); + return Err(InvalidTransaction::RejectCallerWithCode); } } // Check that the transaction's nonce is correct if !context.cfg().is_nonce_check_disabled() { let tx = tx.nonce(); - let state = account.info.nonce; + let state = account.nonce; match tx.cmp(&state) { Ordering::Greater => { - return Err(InvalidTransaction::NonceTooHigh { tx, state }.into()); + return Err(InvalidTransaction::NonceTooHigh { tx, state }); } Ordering::Less => { - return Err(InvalidTransaction::NonceTooLow { tx, state }.into()); + return Err(InvalidTransaction::NonceTooLow { tx, state }); } _ => {} } @@ -320,29 +281,25 @@ where // Check if account has enough balance for `gas_limit * max_fee`` and value transfer. // Transfer will be done inside `*_inner` functions. - if balance_check > account.info.balance && !context.cfg().is_balance_check_disabled() { + if balance_check > account.balance && !context.cfg().is_balance_check_disabled() { return Err(InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(balance_check), - balance: Box::new(account.info.balance), - } - .into()); + balance: Box::new(account.balance), + }); } Ok(()) } /// Validate initial transaction gas. -pub fn validate_initial_tx_gas( - tx: TransactionT, - spec_id: SpecId, -) -> Result -where - TransactionT: Transaction, -{ +pub fn validate_initial_tx_gas( + tx: impl Transaction, + spec: SpecId, +) -> Result { let (accounts, storages) = tx.access_list_nums().unwrap_or_default(); let gas = gas::calculate_initial_tx_gas( - spec_id, + spec, tx.input(), tx.kind().is_create(), accounts as u64, @@ -357,7 +314,7 @@ where // EIP-7623: Increase calldata cost // floor gas should be less than gas limit. - if spec_id.is_enabled_in(SpecId::PRAGUE) && gas.floor_gas > tx.gas_limit() { + if spec.is_enabled_in(SpecId::PRAGUE) && gas.floor_gas > tx.gas_limit() { return Err(InvalidTransaction::GasFloorMoreThanGasLimit); }; @@ -365,6 +322,7 @@ where } /// Helper trait that summarizes ValidationHandler requirements from Context. +/// pub trait EthValidationContext: TransactionGetter + BlockGetter + JournalGetter + CfgGetter { diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 19746ef499..c93a52f699 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -1,30 +1,26 @@ use crate::{ - inspector_context::InspectorContext, inspector_instruction::InspectorInstructionProvider, journal::{JournalExt, JournalExtGetter}, }; use auto_impl::auto_impl; use revm::{ context_interface::{ - BlockGetter, CfgGetter, ErrorGetter, Journal, JournalDBError, JournalGetter, - TransactionGetter, + result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, ResultAndState}, + DatabaseGetter, Journal, }, - database_interface::{Database, EmptyDB}, + database_interface::Database, handler::{ - EthExecution, EthFrame, EthHandler, EthPostExecution, EthPreExecution, - EthPrecompileProvider, EthValidation, FrameResult, + handler::{EthContext, EthError, EthHandler as EthHandlerNew, EthHandlerImpl}, + EthFrame, EthPrecompileProvider, FrameContext, FrameResult, }, - handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}, + handler_interface::{Frame, ItemOrResult, PrecompileProvider}, interpreter::{ - interpreter::EthInterpreter, - interpreter_types::{Jumps, LoopControl}, - table::CustomInstruction, - CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, FrameInput, Host, - Instruction, InstructionResult, Interpreter, InterpreterResult, InterpreterTypes, + interpreter::EthInterpreter, CallInputs, CallOutcome, CreateInputs, CreateOutcome, + EOFCreateInputs, FrameInput, Interpreter, InterpreterTypes, }, - precompile::PrecompileErrors, primitives::{Address, Log, U256}, - Context, Error, Evm, + specification::hardfork::SpecId, + Context, DatabaseCommit, }; /// EVM [Interpreter] callbacks. @@ -162,6 +158,7 @@ pub trait GetInspector { fn get_inspector(&mut self) -> &mut impl Inspector; } +#[auto_impl(&mut, Box)] pub trait InspectorCtx { type IT: InterpreterTypes; @@ -191,176 +188,192 @@ impl + JournalExt, } } -#[derive(Clone)] -pub struct InspectorInstruction { - pub instruction: fn(&mut Interpreter, &mut HOST), +pub struct InspectorHandlerImpl { + pub handler: HANDLER, + _phantom: core::marker::PhantomData<(CTX, ERROR, FRAME, PRECOMPILES, INSTRUCTIONS)>, } -impl CustomInstruction for InspectorInstruction -where - HOST: InspectorCtx, +impl + InspectorHandlerImpl { - type Wire = IT; - type Host = HOST; - - fn exec(&self, interpreter: &mut Interpreter, host: &mut Self::Host) { - // SAFETY: As the PC was already incremented we need to subtract 1 to preserve the - // old Inspector behavior. - interpreter.bytecode.relative_jump(-1); - - // Call step. - host.step(interpreter); - if interpreter.control.instruction_result() != InstructionResult::Continue { - return; + pub fn new(handler: HANDLER) -> Self { + Self { + handler, + _phantom: core::marker::PhantomData, } - - // Reset PC to previous value. - interpreter.bytecode.relative_jump(1); - - // Execute instruction. - (self.instruction)(interpreter, host); - - // Call step_end. - host.step_end(interpreter); } +} - fn from_base(instruction: Instruction) -> Self { - Self { instruction } - } +pub trait FrameInterpreterGetter { + type IT: InterpreterTypes; + + fn interpreter(&mut self) -> &mut Interpreter; } -pub struct InspectorEthFrame -where - CTX: Host, +impl FrameInterpreterGetter + for EthFrame { - // TODO : For now, hardcode the InstructionProvider. But in future this should be configurable as generic parameter. - pub eth_frame: EthFrame< - CTX, - ERROR, - EthInterpreter<()>, - PRECOMPILE, - InspectorInstructionProvider, CTX>, - >, + type IT = IW; + + fn interpreter(&mut self) -> &mut Interpreter { + &mut self.interpreter + } } -impl Frame for InspectorEthFrame +impl EthHandlerNew + for InspectorHandlerImpl where - CTX: TransactionGetter - + ErrorGetter> - + BlockGetter - + JournalGetter - + CfgGetter - + JournalExtGetter - + Host - + InspectorCtx, - ERROR: From> + From, - PRECOMPILE: PrecompileProvider, + CTX: EthContext + InspectorCtx + JournalExtGetter, + INTR: InterpreterTypes, + ERROR: EthError, + // TODO `FrameResult` should be a generic trait. + // TODO `FrameInit` should be a generic. + FRAME: Frame< + Context = CTX, + Error = ERROR, + FrameResult = FrameResult, + FrameInit = FrameInput, + FrameContext = FrameContext>, + > + FrameInterpreterGetter, + PRECOMPILES: PrecompileProvider, + HANDLER: EthHandlerNew, { type Context = CTX; type Error = ERROR; - type FrameInit = FrameInput; - type FrameResult = FrameResult; + type Frame = FRAME; + type Precompiles = PRECOMPILES; + type Instructions = InspectorInstructionProvider; + type HaltReason = ::HaltReason; - fn init_first( - context: &mut CTX, - mut frame_input: Self::FrameInit, - ) -> Result, Self::Error> { + fn frame_context( + &mut self, + context: &mut Self::Context, + ) -> ::FrameContext { + FrameContext::new( + self.handler.frame_context(context).precompiles, + InspectorInstructionProvider::new(), + ) + } + + fn frame_init_first( + &mut self, + context: &mut Self::Context, + frame_context: &mut <::Frame as Frame>::FrameContext, + mut frame_input: <::Frame as Frame>::FrameInit, + ) -> Result< + ItemOrResult< + ::Frame, + <::Frame as Frame>::FrameResult, + >, + Self::Error, + > { if let Some(output) = context.frame_start(&mut frame_input) { - return Ok(FrameOrResultGen::Result(output)); + return Ok(ItemOrResult::Result(output)); } - let mut ret = EthFrame::init_first(context, frame_input) - .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })); + let mut ret = self + .handler + .frame_init_first(context, frame_context, frame_input); match &mut ret { - Ok(FrameOrResultGen::Result(res)) => { + Ok(ItemOrResult::Result(res)) => { context.frame_end(res); } - Ok(FrameOrResultGen::Frame(frame)) => { - context.initialize_interp(&mut frame.eth_frame.interpreter); + Ok(ItemOrResult::Item(frame)) => { + context.initialize_interp(frame.interpreter()); } _ => (), } ret } - fn final_return( - context: &mut Self::Context, - result: &mut Self::FrameResult, - ) -> Result<(), Self::Error> { - context.frame_end(result); - Ok(()) - } - - fn init( + fn frame_init( &self, - context: &mut CTX, - mut frame_input: Self::FrameInit, - ) -> Result, Self::Error> { + frame: &Self::Frame, + context: &mut Self::Context, + frame_context: &mut <::Frame as Frame>::FrameContext, + mut frame_input: <::Frame as Frame>::FrameInit, + ) -> Result< + ItemOrResult< + ::Frame, + <::Frame as Frame>::FrameResult, + >, + Self::Error, + > { if let Some(output) = context.frame_start(&mut frame_input) { - return Ok(FrameOrResultGen::Result(output)); + return Ok(ItemOrResult::Result(output)); } let mut ret = self - .eth_frame - .init(context, frame_input) - .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })); - - if let Ok(FrameOrResultGen::Frame(frame)) = &mut ret { - context.initialize_interp(&mut frame.eth_frame.interpreter); + .handler + .frame_init(frame, context, frame_context, frame_input); + match &mut ret { + Ok(ItemOrResult::Result(res)) => { + context.frame_end(res); + } + Ok(ItemOrResult::Item(frame)) => { + context.initialize_interp(frame.interpreter()); + } + _ => (), } ret } - fn run( + fn frame_return_result( &mut self, - context: &mut CTX, - ) -> Result, Self::Error> { - self.eth_frame.run(context) + frame: &mut Self::Frame, + context: &mut Self::Context, + frame_context: &mut <::Frame as Frame>::FrameContext, + mut result: <::Frame as Frame>::FrameResult, + ) -> Result<(), Self::Error> { + context.frame_end(&mut result); + self.handler + .frame_return_result(frame, context, frame_context, result) } - fn return_result( - &mut self, - context: &mut CTX, - mut result: Self::FrameResult, + fn frame_final_return( + context: &mut Self::Context, + _frame_context: &mut <::Frame as Frame>::FrameContext, + result: &mut <::Frame as Frame>::FrameResult, ) -> Result<(), Self::Error> { - context.frame_end(&mut result); - self.eth_frame.return_result(context, result) + context.frame_end(result); + Ok(()) } } -pub type InspCtxType = InspectorContext; - -pub type InspectorMainEvm = Evm< - Error, - InspCtxType, - EthHandler< - InspCtxType, - Error, - EthValidation, Error>, - EthPreExecution, Error>, - InspectorEthExecution, Error>, - >, ->; - -/// Function to create Inspector Handler. -pub fn inspector_handler() -> InspectorHandler -{ - EthHandler::new( - EthValidation::new(), - EthPreExecution::new(), - EthExecution::<_, _, InspectorEthFrame<_, _, PRECOMPILE>>::new(), - EthPostExecution::new(), - ) +pub fn inspect_main< + DB: Database, + CTX: EthContext + + JournalExtGetter + + DatabaseGetter + + InspectorCtx, +>( + ctx: &mut CTX, +) -> Result, EVMError<::Error, InvalidTransaction>> { + InspectorHandlerImpl::< + _, + _, + EthFrame<_, _, _, _>, + _, + _, + InspectorInstructionProvider, + >::new(EthHandlerImpl { + precompiles: EthPrecompileProvider::new(SpecId::LATEST), + instructions: InspectorInstructionProvider::new(), + _phantom: core::marker::PhantomData, + }) + .run(ctx) } -/// Composed type for Inspector Execution handler. -pub type InspectorEthExecution> = - EthExecution>; - -/// Composed type for Inspector Handler. -pub type InspectorHandler = EthHandler< - CTX, - ERROR, - EthValidation, - EthPreExecution, - InspectorEthExecution, ->; +pub fn inspect_main_commit< + DB: Database + DatabaseCommit, + CTX: EthContext + + JournalExtGetter + + DatabaseGetter + + InspectorCtx, +>( + ctx: &mut CTX, +) -> Result, EVMError<::Error, InvalidTransaction>> { + inspect_main(ctx).map(|res| { + ctx.db().commit(res.state); + res.result + }) +} diff --git a/crates/inspector/src/inspector_context.rs b/crates/inspector/src/inspector_context.rs index 2bb39169b5..74faa10abc 100644 --- a/crates/inspector/src/inspector_context.rs +++ b/crates/inspector/src/inspector_context.rs @@ -5,7 +5,7 @@ use revm::{ PerformantContextAccess, TransactionGetter, }, database_interface::Database, - handler::FrameResult, + handler::{handler::EthContext, FrameResult}, interpreter::{ interpreter::EthInterpreter, FrameInput, Host, Interpreter, SStoreResult, SelfDestructResult, StateLoad, @@ -27,6 +27,22 @@ where pub frame_input_stack: Vec, } +impl< + INSP: Inspector, + DB: Database, + CTX: EthContext + DatabaseGetter, + > EthContext for InspectorContext +{ +} + +impl< + INSP: Inspector, + DB: Database, + CTX: EthContext + DatabaseGetter, + > EthContext for &mut InspectorContext +{ +} + impl InspectorContext where CTX: BlockGetter @@ -109,7 +125,7 @@ where INSP: GetInspector, CTX: DatabaseGetter, { - type IT = EthInterpreter<()>; + type IT = EthInterpreter; fn step(&mut self, interp: &mut Interpreter) { self.inspector.get_inspector().step(interp, &mut self.inner); diff --git a/crates/inspector/src/inspector_instruction.rs b/crates/inspector/src/inspector_instruction.rs index 5a00ff3171..a979d205ca 100644 --- a/crates/inspector/src/inspector_instruction.rs +++ b/crates/inspector/src/inspector_instruction.rs @@ -5,7 +5,7 @@ use revm::{ interpreter::{ instructions::host::{log, selfdestruct}, interpreter::InstructionProvider, - interpreter_types::LoopControl, + interpreter_types::{Jumps, LoopControl}, table::{self, CustomInstruction}, Host, Instruction, InstructionResult, Interpreter, InterpreterTypes, }, @@ -15,9 +15,47 @@ use std::rc::Rc; use crate::{ journal::{JournalExt, JournalExtGetter}, - InspectorCtx, InspectorInstruction, + InspectorCtx, }; +#[derive(Clone)] +pub struct InspectorInstruction { + pub instruction: fn(&mut Interpreter, &mut HOST), +} + +impl CustomInstruction for InspectorInstruction +where + HOST: InspectorCtx, +{ + type Wire = IT; + type Host = HOST; + + fn exec(&self, interpreter: &mut Interpreter, host: &mut Self::Host) { + // SAFETY: As the PC was already incremented we need to subtract 1 to preserve the + // old Inspector behavior. + interpreter.bytecode.relative_jump(-1); + + // Call step. + host.step(interpreter); + if interpreter.control.instruction_result() != InstructionResult::Continue { + return; + } + + // Reset PC to previous value. + interpreter.bytecode.relative_jump(1); + + // Execute instruction. + (self.instruction)(interpreter, host); + + // Call step_end. + host.step_end(interpreter); + } + + fn from_base(instruction: Instruction) -> Self { + Self { instruction } + } +} + pub struct InspectorInstructionProvider { instruction_table: Rc<[InspectorInstruction; 256]>, } @@ -33,15 +71,12 @@ where } } -impl InstructionProvider for InspectorInstructionProvider +impl InspectorInstructionProvider where WIRE: InterpreterTypes, HOST: Host + JournalExtGetter + JournalGetter + InspectorCtx, { - type WIRE = WIRE; - type Host = HOST; - - fn new(_context: &mut Self::Host) -> Self { + pub fn new() -> Self { let main_table = table::make_instruction_table::(); let mut table: [MaybeUninit>; 256] = unsafe { MaybeUninit::uninit().assume_init() }; @@ -103,7 +138,7 @@ where table[OpCode::SELFDESTRUCT.as_usize()] = InspectorInstruction { instruction: |interp, context| { - selfdestruct::(interp, context); + selfdestruct::(interp, context); if interp.control.instruction_result() == InstructionResult::SelfDestruct { match context.journal_ext().last_journal().last() { Some(JournalEntry::AccountDestroyed { @@ -129,8 +164,27 @@ where instruction_table: Rc::new(table), } } +} + +impl InstructionProvider for InspectorInstructionProvider +where + WIRE: InterpreterTypes, + HOST: Host + JournalExtGetter + JournalGetter + InspectorCtx, +{ + type WIRE = WIRE; + type Host = HOST; fn table(&mut self) -> &[impl CustomInstruction; 256] { self.instruction_table.as_ref() } } + +impl Default for InspectorInstructionProvider +where + WIRE: InterpreterTypes, + HOST: Host + JournalExtGetter + JournalGetter + InspectorCtx, +{ + fn default() -> Self { + Self::new() + } +} diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index ddcf245bb0..f4cc1df6ea 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -129,7 +129,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - parse opcodes from strings ([#1358](https://github.com/bluealloy/revm/pull/1358)) - *(interpreter)* add helpers for spending all gas ([#1360](https://github.com/bluealloy/revm/pull/1360)) - add helper methods to CallInputs ([#1345](https://github.com/bluealloy/revm/pull/1345)) -- *(revm)* make `FrameOrResult` serializable ([#1282](https://github.com/bluealloy/revm/pull/1282)) +- *(revm)* make `ItemOrResult` serializable ([#1282](https://github.com/bluealloy/revm/pull/1282)) - add flag to force hashbrown usage ([#1284](https://github.com/bluealloy/revm/pull/1284)) - EOF (Ethereum Object Format) ([#1143](https://github.com/bluealloy/revm/pull/1143)) - *(interpreter)* derive Eq for InterpreterAction ([#1262](https://github.com/bluealloy/revm/pull/1262)) diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 32bd8efd19..efd3dbf2a9 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -27,7 +27,6 @@ bytecode.workspace = true primitives.workspace = true specification.workspace = true context-interface.workspace = true -handler-interface.workspace = true # optional serde = { version = "1.0", default-features = false, features = [ diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index d622625e94..ea72672a48 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,7 +1,6 @@ use super::constants::*; use crate::{num_words, tri, SStoreResult, SelfDestructResult, StateLoad}; use context_interface::journaled_state::AccountLoad; -use handler_interface::InitialAndFloorGas; use primitives::U256; use specification::{eip7702, hardfork::SpecId}; @@ -347,6 +346,16 @@ pub const fn memory_gas(num_words: usize) -> u64 { .saturating_add(num_words.saturating_mul(num_words) / 512) } +/// Init and floor gas from transaction +#[derive(Clone, Copy, Debug, Default)] +pub struct InitialAndFloorGas { + /// Initial gas for transaction. + pub initial_gas: u64, + /// If transaction is a Call and Prague is enabled + /// floor_gas is at least amount of gas that is going to be spent. + pub floor_gas: u64, +} + /// Initial gas that is deducted for transaction to be included. /// Initial gas contains initial stipend gas, gas for access list and input data. /// diff --git a/crates/interpreter/src/instructions.rs b/crates/interpreter/src/instructions.rs index baed840373..1e6e850706 100644 --- a/crates/interpreter/src/instructions.rs +++ b/crates/interpreter/src/instructions.rs @@ -226,7 +226,6 @@ mod tests { // use crate::DummyHost; // use bytecode::opcode::*; - // TODO : Define EthEthereumWire // #[test] // fn all_instructions_and_opcodes_used() { // // known unknown instruction we compare it with other instructions from table. diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index cd881fdd8a..566dae809f 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -35,7 +35,6 @@ pub fn push( _host: &mut H, ) { gas!(interpreter, gas::VERYLOW); - // TODO : Check performance degradation. push!(interpreter, U256::ZERO); popn_top!([], top, interpreter); diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 827d8b7589..ca7968c23c 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -92,11 +92,15 @@ pub trait InstructionProvider: Clone { type WIRE: InterpreterTypes; type Host; - fn new(context: &mut Self::Host) -> Self; - fn table(&mut self) -> &[impl CustomInstruction; 256]; } +pub trait InstructionProviderGetter { + type InstructionProvider: InstructionProvider; + + fn instructions(&mut self) -> &mut Self::InstructionProvider; +} + pub struct EthInstructionProvider { instruction_table: Rc<[Instruction; 256]>, } @@ -112,22 +116,27 @@ where } } -impl InstructionProvider for EthInstructionProvider +impl EthInstructionProvider where WIRE: InterpreterTypes, HOST: Host, { - type WIRE = WIRE; - type Host = HOST; - - fn new(_context: &mut Self::Host) -> Self { + pub fn new() -> Self { Self { instruction_table: Rc::new(crate::table::make_instruction_table::()), } } +} - // TODO : Make impl a associate type. With this associate type we can implement. - // InspectorInstructionProvider over generic type. +impl InstructionProvider for EthInstructionProvider +where + WIRE: InterpreterTypes, + HOST: Host, +{ + type WIRE = WIRE; + type Host = HOST; + + /// Returns the instruction table. fn table(&mut self) -> &[impl CustomInstruction; 256] { self.instruction_table.as_ref() } @@ -244,21 +253,15 @@ impl InterpreterResult { } } -// /// Resize the memory to the new size. Returns whether the gas was enough to resize the memory. -// #[inline(never)] -// #[cold] -// #[must_use] -// pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) -> bool { -// let new_words = num_words(new_size as u64); -// let new_cost = gas::memory_gas(new_words); -// let current_cost = memory.current_expansion_cost(); -// let cost = new_cost - current_cost; -// let success = gas.record_cost(cost); -// if success { -// memory.resize((new_words as usize) * 32); -// } -// success -// } +impl Default for EthInstructionProvider +where + WIRE: InterpreterTypes, + HOST: Host, +{ + fn default() -> Self { + Self::new() + } +} #[cfg(test)] mod tests { diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index db4d1ff731..8d8f4c3a60 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -269,7 +269,7 @@ impl Stack { unsafe { // Note: `ptr::swap_nonoverlapping` is more efficient than `slice::swap` or `ptr::swap` // because it operates under the assumption that the pointers do not overlap, - // eliminating an intemediate copy, + // eliminating an intermediate copy, // which is a condition we know to be true in this context. let top = self.data.as_mut_ptr().add(len - 1); core::ptr::swap_nonoverlapping(top.sub(n), top.sub(n_m_index), 1); diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 46e0490699..05bec1a828 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -30,7 +30,7 @@ pub use context_interface::{ host::{DummyHost, Host, SStoreResult, SelfDestructResult, StateLoad}, CreateScheme, }; -pub use gas::Gas; +pub use gas::{Gas, InitialAndFloorGas}; pub use instruction_result::*; pub use interpreter::{ num_words, InputsImpl, Interpreter, InterpreterResult, MemoryGetter, SharedMemory, Stack, diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index 8190befb22..de26584f1b 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -25,7 +25,7 @@ all = "warn" # revm revm.workspace = true precompile = { workspace = true, features = ["secp256r1"] } -inspector.workspace = true +#inspector.workspace = true # static precompile sets. once_cell = { version = "1.19", default-features = false, features = ["alloc"] } diff --git a/crates/optimism/src/evm.rs b/crates/optimism/src/evm.rs deleted file mode 100644 index d1674a7806..0000000000 --- a/crates/optimism/src/evm.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::{ - handler::{ - precompiles::OpPrecompileProvider, OpExecution, OpHandler, OpPreExecution, OpValidation, - }, - L1BlockInfo, OpSpec, OpTransaction, -}; -use inspector::{inspector_context::InspectorContext, InspectorEthFrame}; -use revm::{ - context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context}, - context_interface::result::{EVMError, InvalidTransaction}, - database_interface::Database, - Evm, JournaledState, -}; - -/// Optimism Error -pub type OpError = EVMError<::Error, InvalidTransaction>; - -/// Optimism Context -pub type OpContext = Context, CfgEnv, DB, L1BlockInfo>; - -/// Optimism EVM type -pub type OpEvm = Evm, OpContext, OpHandler, OpError>>; - -pub type InspCtxType = InspectorContext< - INSP, - DB, - Context, DB, JournaledState, L1BlockInfo>, ->; - -pub type InspectorOpEvm = Evm< - OpError, - InspCtxType, - OpHandler< - InspCtxType, - OpError, - OpValidation, OpError>, - OpPreExecution, OpError>, - OpExecution< - InspCtxType, - OpError, - InspectorEthFrame< - InspCtxType, - OpError, - OpPrecompileProvider, OpError>, - >, - >, - >, ->; diff --git a/crates/optimism/src/handler.rs b/crates/optimism/src/handler.rs index 9b5256b43c..dde96adb25 100644 --- a/crates/optimism/src/handler.rs +++ b/crates/optimism/src/handler.rs @@ -10,25 +10,16 @@ use crate::{ }, L1BlockInfoGetter, OpSpec, OpSpecId, OptimismHaltReason, BASE_FEE_RECIPIENT, L1_FEE_RECIPIENT, }; -use precompiles::OpPrecompileProvider; use revm::{ context_interface::{ result::{ExecutionResult, FromStringError, InvalidTransaction, ResultAndState}, - Block, Cfg, CfgGetter, DatabaseGetter, Journal, Transaction, TransactionGetter, - }, - handler::{ - EthExecution, EthExecutionContext, EthExecutionError, EthFrame, EthFrameContext, - EthFrameError, EthHandler, EthPostExecution, EthPostExecutionContext, - EthPostExecutionError, EthPreExecution, EthPreExecutionContext, EthPreExecutionError, - EthValidation, EthValidationContext, EthValidationError, FrameResult, - }, - handler_interface::{ - util::FrameOrFrameResult, ExecutionHandler, Frame, InitialAndFloorGas, - PostExecutionHandler, PreExecutionHandler, ValidationHandler, + Block, Cfg, CfgGetter, Journal, Transaction, TransactionGetter, }, + handler::{EthContext, EthError, EthHandler, EthHandlerImpl, FrameContext, FrameResult}, + handler_interface::{Frame, PrecompileProvider}, interpreter::{ - interpreter::{EthInstructionProvider, EthInterpreter}, - FrameInput, Gas, + interpreter::{EthInterpreter, InstructionProvider}, + FrameInput, Gas, Host, }, primitives::{hash_map::HashMap, U256}, specification::hardfork::SpecId, @@ -36,33 +27,59 @@ use revm::{ Database, }; -pub type OpHandler< - CTX, - ERROR, - VAL = OpValidation, - PREEXEC = OpPreExecution, - EXEC = OpExecution, - POSTEXEC = OpPostExecution, -> = EthHandler; - -pub struct OpValidation { - pub eth: EthValidation, +pub struct OpHandlerNew { + pub eth: EthHandlerImpl, } -impl ValidationHandler for OpValidation +impl + OpHandlerNew where - CTX: EthValidationContext + OpTxGetter, + PRECOMPILES: PrecompileProvider, + INSTRUCTIONS: InstructionProvider, +{ + pub fn crete_frame_context(&self) -> FrameContext { + self.eth.crete_frame_context() + } +} + +pub trait IsTxError { + fn is_tx_error(&self) -> bool; +} + +impl EthHandler + for OpHandlerNew +where + CTX: EthContext + OpTxGetter + L1BlockInfoGetter, // Have Cfg with OpSpec ::Cfg: Cfg, - // Have transaction with OpTransactionType - //::Transaction: Transaction, - // Add additional error type. - ERROR: EthValidationError + From, + ERROR: EthError + From + IsTxError + FromStringError, + PRECOMPILES: PrecompileProvider, + INSTRUCTIONS: InstructionProvider, + // TODO `FrameResult` should be a generic trait. + // TODO `FrameInit` should be a generic. + FRAME: Frame< + Context = CTX, + Error = ERROR, + FrameResult = FrameResult, + FrameInit = FrameInput, + FrameContext = FrameContext, + >, { type Context = CTX; type Error = ERROR; + type Frame = FRAME; + type Precompiles = PRECOMPILES; + type Instructions = INSTRUCTIONS; + type HaltReason = OptimismHaltReason; + + fn frame_context( + &mut self, + context: &mut Self::Context, + ) -> ::FrameContext { + self.eth.precompiles.set_spec(context.cfg().spec()); + self.crete_frame_context() + } - /// Validate env. fn validate_env(&self, context: &Self::Context) -> Result<(), Self::Error> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. let tx_type = context.tx().tx_type(); @@ -78,7 +95,6 @@ where self.eth.validate_env(context) } - /// Validate transactions against state. fn validate_tx_against_state(&self, context: &mut Self::Context) -> Result<(), Self::Error> { if context.tx().tx_type() == DEPOSIT_TRANSACTION_TYPE { return Ok(()); @@ -86,28 +102,6 @@ where self.eth.validate_tx_against_state(context) } - /// Validate initial gas. - fn validate_initial_tx_gas( - &self, - context: &Self::Context, - ) -> Result { - self.eth.validate_initial_tx_gas(context) - } -} - -pub struct OpPreExecution { - pub eth: EthPreExecution, -} - -impl PreExecutionHandler for OpPreExecution -where - CTX: EthPreExecutionContext + DatabaseGetter + OpTxGetter + L1BlockInfoGetter, - ::Cfg: Cfg, - ERROR: EthPreExecutionError + From<<::Database as Database>::Error>, -{ - type Context = CTX; - type Error = ERROR; - fn load_accounts(&self, context: &mut Self::Context) -> Result<(), Self::Error> { // The L1-cost fee is only computed for Optimism non-deposit transactions. let spec = context.cfg().spec(); @@ -122,10 +116,6 @@ where self.eth.load_accounts(context) } - fn apply_eip7702_auth_list(&self, context: &mut Self::Context) -> Result { - self.eth.apply_eip7702_auth_list(context) - } - fn deduct_caller(&self, context: &mut Self::Context) -> Result<(), Self::Error> { let caller = context.tx().caller(); let is_deposit = context.tx().tx_type() == DEPOSIT_TRANSACTION_TYPE; @@ -171,48 +161,13 @@ where } Ok(()) } -} - -pub struct OpExecution< - CTX, - ERROR, - FRAME = EthFrame< - CTX, - ERROR, - EthInterpreter<()>, - OpPrecompileProvider, - EthInstructionProvider, CTX>, - >, -> { - pub eth: EthExecution, -} - -impl ExecutionHandler for OpExecution -where - CTX: EthExecutionContext + EthFrameContext + OpTxGetter, - ERROR: EthExecutionError + EthFrameError, - ::Cfg: Cfg, - //::Transaction: Transaction, - FRAME: Frame, -{ - type Context = CTX; - type Error = ERROR; - type Frame = FRAME; - type ExecResult = FrameResult; - - fn init_first_frame( - &mut self, - context: &mut Self::Context, - gas_limit: u64, - ) -> Result, Self::Error> { - self.eth.init_first_frame(context, gas_limit) - } fn last_frame_result( &self, context: &mut Self::Context, - mut frame_result: ::FrameResult, - ) -> Result { + _frame_context: &mut ::FrameContext, + frame_result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { let tx = context.tx(); let is_deposit = tx.tx_type() == DEPOSIT_TRANSACTION_TYPE; let tx_gas_limit = tx.gas_limit(); @@ -270,48 +225,13 @@ where gas.erase_cost(remaining); } } - Ok(frame_result) - } -} - -pub struct OpPostExecution { - pub eth: EthPostExecution, -} - -pub trait IsTxError { - fn is_tx_error(&self) -> bool; -} - -impl PostExecutionHandler for OpPostExecution -where - CTX: EthPostExecutionContext + OpTxGetter + L1BlockInfoGetter + DatabaseGetter, - ERROR: EthPostExecutionError - + EthFrameError - + From - + FromStringError - + IsTxError, - ::Cfg: Cfg, - //::Transaction: Transaction, -{ - type Context = CTX; - type Error = ERROR; - type ExecResult = FrameResult; - type Output = ResultAndState; - - fn eip7623_check_gas_floor( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - init_and_floor_gas: InitialAndFloorGas, - ) { - self.eth - .eip7623_check_gas_floor(context, exec_result, init_and_floor_gas); + Ok(()) } fn refund( &self, context: &mut Self::Context, - exec_result: &mut Self::ExecResult, + exec_result: &mut ::FrameResult, eip7702_refund: i64, ) { exec_result.gas_mut().record_refund(eip7702_refund); @@ -328,18 +248,10 @@ where } } - fn reimburse_caller( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error> { - self.eth.reimburse_caller(context, exec_result) - } - fn reward_beneficiary( &self, context: &mut Self::Context, - exec_result: &mut Self::ExecResult, + exec_result: &mut ::FrameResult, ) -> Result<(), Self::Error> { self.eth.reward_beneficiary(context, exec_result)?; @@ -380,9 +292,10 @@ where fn output( &self, context: &mut Self::Context, - result: Self::ExecResult, - ) -> Result { + result: ::FrameResult, + ) -> Result, Self::Error> { let result = self.eth.output(context, result)?; + let result = result.map_haltreason(OptimismHaltReason::Base); if result.result.is_halt() { // Post-regolith, if the transaction is a deposit transaction and it halts, // we bubble up to the global return handler. The mint value will be persisted @@ -395,15 +308,11 @@ where Ok(result) } - fn clear(&self, context: &mut Self::Context) { - self.eth.clear(context); - } - fn end( &self, context: &mut Self::Context, - end_output: Result, - ) -> Result { + end_output: Result, Self::Error>, + ) -> Result, Self::Error> { //end_output let is_deposit = context.tx().tx_type() == DEPOSIT_TRANSACTION_TYPE; @@ -466,16 +375,6 @@ where } } -// /// Optimism end handle changes output if the transaction is a deposit transaction. -// /// Deposit transaction can't be reverted and is always successful. -// #[inline] -// pub fn end( -// context: &mut Context, -// evm_output: EVMResult, -// ) -> EVMResult { - -// } - // #[cfg(test)] // mod tests { // use super::*; diff --git a/crates/optimism/src/handler/precompiles.rs b/crates/optimism/src/handler/precompiles.rs index 73a0d63738..1519d08138 100644 --- a/crates/optimism/src/handler/precompiles.rs +++ b/crates/optimism/src/handler/precompiles.rs @@ -29,43 +29,9 @@ impl OpPrecompileProvider { }, } } -} - -/// Returns precompiles for Fjor spec. -pub fn fjord() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); - INSTANCE.get_or_init(|| { - let mut precompiles = Precompiles::cancun().clone(); - // EIP-7212: secp256r1 P256verify - precompiles.extend([crate::bn128::pair::GRANITE]); - Box::new(precompiles) - }) -} - -/// Returns precompiles for Granite spec. -pub fn granite() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); - INSTANCE.get_or_init(|| { - let mut precompiles = Precompiles::cancun().clone(); - // Restrict bn256Pairing input size - precompiles.extend([secp256r1::P256VERIFY]); - Box::new(precompiles) - }) -} - -impl PrecompileProvider for OpPrecompileProvider -where - CTX: CfgGetter, - ::Cfg: Cfg, - ERROR: From, -{ - type Context = CTX; - type Error = ERROR; - type Output = InterpreterResult; #[inline] - fn new(context: &mut Self::Context) -> Self { - let spec = context.cfg().spec(); + pub fn new_with_spec(spec: OpSpec) -> Self { match spec { // No changes spec @ (OpSpec::Eth( @@ -101,6 +67,45 @@ where | OpSpec::Eth(SpecId::PRAGUE | SpecId::OSAKA | SpecId::LATEST) => Self::new(granite()), } } +} + +/// Returns precompiles for Fjor spec. +pub fn fjord() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::cancun().clone(); + // EIP-7212: secp256r1 P256verify + precompiles.extend([crate::bn128::pair::GRANITE]); + Box::new(precompiles) + }) +} + +/// Returns precompiles for Granite spec. +pub fn granite() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::cancun().clone(); + // Restrict bn256Pairing input size + precompiles.extend([secp256r1::P256VERIFY]); + Box::new(precompiles) + }) +} + +impl PrecompileProvider for OpPrecompileProvider +where + CTX: CfgGetter, + ::Cfg: Cfg, + ERROR: From, +{ + type Context = CTX; + type Error = ERROR; + type Output = InterpreterResult; + type Spec = OpSpec; + + #[inline] + fn set_spec(&mut self, spec: Self::Spec) { + *self = Self::new_with_spec(spec); + } #[inline] fn run( @@ -115,7 +120,7 @@ where } #[inline] - fn warm_addresses(&self) -> impl Iterator { + fn warm_addresses(&self) -> Box + '_> { self.precompile_provider.warm_addresses() } diff --git a/crates/optimism/src/lib.rs b/crates/optimism/src/lib.rs index 2468597be1..4e5b4de60e 100644 --- a/crates/optimism/src/lib.rs +++ b/crates/optimism/src/lib.rs @@ -6,7 +6,6 @@ extern crate alloc as std; pub mod bn128; -pub mod evm; pub mod fast_lz; pub mod handler; pub mod l1block; diff --git a/crates/optimism/src/spec.rs b/crates/optimism/src/spec.rs index 98c1e64851..38e4079c87 100644 --- a/crates/optimism/src/spec.rs +++ b/crates/optimism/src/spec.rs @@ -51,6 +51,14 @@ impl From for OpSpec { OpSpec::Eth(spec) } } +impl From for SpecId { + fn from(spec: OpSpec) -> Self { + match spec { + OpSpec::Eth(spec) => spec, + OpSpec::Op(spec) => spec.into_eth_spec(), + } + } +} impl TryFrom<&str> for OpSpecId { type Error = (); diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 3810eda0a1..15c4ceb8f3 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -134,7 +134,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add uniswap V2 WETH-USDC swap example ([#1353](https://github.com/bluealloy/revm/pull/1353)) - *(interpreter)* add helpers for spending all gas ([#1360](https://github.com/bluealloy/revm/pull/1360)) - add helper methods to CallInputs ([#1345](https://github.com/bluealloy/revm/pull/1345)) -- *(revm)* make `FrameOrResult` serializable ([#1282](https://github.com/bluealloy/revm/pull/1282)) +- *(revm)* make `ItemOrResult` serializable ([#1282](https://github.com/bluealloy/revm/pull/1282)) - add flag to force hashbrown usage ([#1284](https://github.com/bluealloy/revm/pull/1284)) - EOF (Ethereum Object Format) ([#1143](https://github.com/bluealloy/revm/pull/1143)) - *(`db`)* Introduce `alloydb` ([#1257](https://github.com/bluealloy/revm/pull/1257)) diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index ef962a13d7..994fe73e8b 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -35,13 +35,6 @@ context-interface.workspace = true handler.workspace = true handler-interface.workspace = true -# Optional -# TODO : Check if needed. -# serde = { version = "1.0", default-features = false, features = [ -# "derive", -# "rc", -# ], optional = true } - [dev-dependencies] database.workspace = true alloy-sol-types = { version = "0.8.2", default-features = false, features = [ diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 72d503b278..597b190bd5 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -1,297 +1,30 @@ -use crate::{exec::EvmCommit, EvmExec}; -use context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context, JournaledState}; use context_interface::{ - block::BlockSetter, - context::PerformantContextAccess, - journaled_state::Journal, - result::{ - EVMError, ExecutionResult, HaltReasonTrait, InvalidHeader, InvalidTransaction, - ResultAndState, - }, - transaction::TransactionSetter, - BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, JournalDBError, JournalGetter, - Transaction, TransactionGetter, + result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, ResultAndState}, + DatabaseGetter, }; use database_interface::{Database, DatabaseCommit}; -use handler::{EthHandler, FrameResult}; -use handler_interface::{ - ExecutionHandler, Frame, FrameOrResultGen, Handler, InitialAndFloorGas, PostExecutionHandler, - PreExecutionHandler, ValidationHandler, +use handler::{ + handler::{EthContext, EthHandler, EthHandlerImpl}, + EthFrame, EthPrecompileProvider, }; -use interpreter::Host; -use precompile::PrecompileErrors; -use primitives::Log; -use state::EvmState; -use std::vec::Vec; -/// Main EVM structure -pub struct Evm> { - pub context: CTX, - pub handler: HANDLER, - pub _error: core::marker::PhantomData ERROR>, +pub fn transact_main>( + ctx: &mut CTX, +) -> Result, EVMError<::Error, InvalidTransaction>> { + EthHandlerImpl::, EthPrecompileProvider, _>::default() + .run(ctx) } -impl Evm { - pub fn new(context: CTX, handler: HANDLER) -> Self { - Self { - context, - handler, - _error: core::marker::PhantomData, - } - } -} - -impl EvmCommit - for Evm> -where - CTX: TransactionSetter - + BlockSetter - + JournalGetter - + CfgGetter - + DatabaseGetter - + ErrorGetter> - + JournalGetter< - Journal: Journal< - FinalOutput = (EvmState, Vec), - Database = ::Database, - >, - > + Host - + PerformantContextAccess::Database as Database>::Error>, - ERROR: From - + From - + From> - + From, - VAL: ValidationHandler, - PREEXEC: PreExecutionHandler, - EXEC: ExecutionHandler< - Context = CTX, - Error = ERROR, - ExecResult = FrameResult, - Frame: Frame, - >, - POSTEXEC: PostExecutionHandler< - Context = CTX, - Error = ERROR, - ExecResult = FrameResult, - // TODO make output more generics - Output = ResultAndState, - >, - HALT: HaltReasonTrait, -{ - type CommitOutput = Result, ERROR>; - - fn exec_commit(&mut self) -> Self::CommitOutput { - let res = self.transact(); - res.map(|r| { - self.context.db().commit(r.state); - r.result - }) - } -} - -impl EvmExec - for Evm> -where - CTX: TransactionSetter - + BlockSetter - + JournalGetter - + CfgGetter - + DatabaseGetter - + ErrorGetter> - + JournalGetter< - Journal: Journal< - FinalOutput = (EvmState, Vec), - Database = ::Database, - >, - > + Host - + PerformantContextAccess::Database as Database>::Error>, - ERROR: From - + From - + From> - + From, - VAL: ValidationHandler, - PREEXEC: PreExecutionHandler, - EXEC: ExecutionHandler< - Context = CTX, - Error = ERROR, - ExecResult = FrameResult, - Frame: Frame, - >, - POSTEXEC: PostExecutionHandler, -{ - type Transaction = ::Transaction; - - type Block = ::Block; - - type Output = Result<::Output, ERROR>; - - fn set_block(&mut self, block: Self::Block) { - self.context.set_block(block); - } - - fn set_tx(&mut self, tx: Self::Transaction) { - self.context.set_tx(tx); - } - - fn exec(&mut self) -> Self::Output { - self.transact() - } -} - -/// Mainnet Error. -pub type Error = EVMError<::Error, InvalidTransaction>; - -/// Mainnet Contexts. -pub type EthContext> = - Context; - -/// Mainnet EVM type. -pub type MainEvm = Evm, EthContext>; - -impl - Evm> -where - CTX: TransactionGetter - + BlockGetter - + JournalGetter - + CfgGetter - + DatabaseGetter - + ErrorGetter> - + JournalGetter< - Journal: Journal< - FinalOutput = (EvmState, Vec), - Database = ::Database, - >, - > + Host - + PerformantContextAccess::Database as Database>::Error>, - ERROR: From - + From - + From> - + From, - VAL: ValidationHandler, - PREEXEC: PreExecutionHandler, - EXEC: ExecutionHandler< - Context = CTX, - Error = ERROR, - ExecResult = FrameResult, - Frame: Frame, - >, - POSTEXEC: PostExecutionHandler, -{ - /// Pre verify transaction by checking Environment, initial gas spend and if caller - /// has enough balance to pay for the gas. - #[inline] - pub fn preverify_transaction(&mut self) -> Result<(), ERROR> { - let output = self.preverify_transaction_inner().map(|_| ()); - self.clear(); - output - } - - /// Calls clear handle of post execution to clear the state for next execution. - fn clear(&mut self) { - self.handler.post_execution().clear(&mut self.context); - } - - /// Transact pre-verified transaction - /// - /// This function will not validate the transaction. - #[inline] - pub fn transact_preverified( - &mut self, - ) -> Result<::Output, ERROR> { - let initial_gas_spend = self - .handler - .validation() - .validate_initial_tx_gas(&self.context) - .inspect_err(|_| { - self.clear(); - })?; - let init_and_floor_gas = self.transact_preverified_inner(initial_gas_spend); - let output = self - .handler - .post_execution() - .end(&mut self.context, init_and_floor_gas); - self.clear(); - output - } - - /// Pre verify transaction inner. - #[inline] - fn preverify_transaction_inner(&mut self) -> Result { - self.handler.validation().validate_env(&self.context)?; - let initial_gas_spend = self - .handler - .validation() - .validate_initial_tx_gas(&self.context)?; - self.handler - .validation() - .validate_tx_against_state(&mut self.context)?; - Ok(initial_gas_spend) - } - - /// Transact transaction - /// - /// This function will validate the transaction. - #[inline] - pub fn transact(&mut self) -> Result<::Output, ERROR> { - let initial_gas_spend = self.preverify_transaction_inner().inspect_err(|_| { - self.clear(); - })?; - - let init_and_floor_gas = self.transact_preverified_inner(initial_gas_spend); - let output = self - .handler - .post_execution() - .end(&mut self.context, init_and_floor_gas); - self.clear(); - output - } - - /// Transact pre-verified transaction. - fn transact_preverified_inner( - &mut self, - init_and_floor_gas: InitialAndFloorGas, - ) -> Result<::Output, ERROR> { - let context = &mut self.context; - let pre_exec = self.handler.pre_execution(); - - // Load access list and beneficiary if needed. - pre_exec.load_accounts(context)?; - - // Deduce caller balance with its limit. - pre_exec.deduct_caller(context)?; - - let gas_limit = context.tx().gas_limit() - init_and_floor_gas.initial_gas; - - // Apply EIP-7702 auth list. - let eip7702_gas_refund = pre_exec.apply_eip7702_auth_list(context)? as i64; - - // Start execution - - //let instructions = self.handler.take_instruction_table(); - let exec = self.handler.execution(); - - // Create first frame action - let first_frame = exec.init_first_frame(context, gas_limit)?; - let frame_result = match first_frame { - FrameOrResultGen::Frame(frame) => exec.run(context, frame)?, - FrameOrResultGen::Result(result) => result, - }; - - let mut exec_result = exec.last_frame_result(context, frame_result)?; - - let post_exec = self.handler.post_execution(); - // Calculate final refund and add EIP-7702 refund to gas. - post_exec.refund(context, &mut exec_result, eip7702_gas_refund); - // Check gas floor - post_exec.eip7623_check_gas_floor(context, &mut exec_result, init_and_floor_gas); - // Reimburse the caller - post_exec.reimburse_caller(context, &mut exec_result)?; - // Reward beneficiary - post_exec.reward_beneficiary(context, &mut exec_result)?; - // Returns output of transaction. - post_exec.output(context, exec_result) - } +pub fn transact_main_commit< + DB: Database + DatabaseCommit, + CTX: EthContext + DatabaseGetter, +>( + ctx: &mut CTX, +) -> Result, EVMError<::Error, InvalidTransaction>> { + transact_main(ctx).map(|r| { + ctx.db().commit(r.state); + r.result + }) } /* diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 865c02a66d..bebfc2f30a 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -2,8 +2,8 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(not(feature = "std"))] -extern crate alloc as std; +//#[cfg(not(feature = "std"))] +//extern crate alloc as std; // reexport dependencies pub use bytecode; @@ -28,5 +28,5 @@ mod exec; pub use context::journaled_state::{JournalEntry, JournaledState}; pub use context::Context; pub use database_interface::{Database, DatabaseCommit, DatabaseRef}; -pub use evm::{Error, EthContext, Evm, MainEvm}; +pub use evm::{transact_main, transact_main_commit}; pub use exec::{EvmCommit, EvmExec}; diff --git a/examples/block_traces/src/main.rs b/examples/block_traces/src/main.rs index ddcde54d89..d174721037 100644 --- a/examples/block_traces/src/main.rs +++ b/examples/block_traces/src/main.rs @@ -9,19 +9,8 @@ use alloy_provider::{ }; use database::{AlloyDB, CacheDB, StateBuilder}; use indicatif::ProgressBar; -use inspector::{ - inspector_context::InspectorContext, inspectors::TracerEip3155, InspectorEthFrame, - InspectorMainEvm, -}; -use revm::{ - database_interface::WrapDatabaseAsync, - handler::{ - EthExecution, EthHandler, EthPostExecution, EthPreExecution, EthPrecompileProvider, - EthValidation, - }, - primitives::TxKind, - Context, EvmCommit, -}; +use inspector::{inspect_main, inspector_context::InspectorContext, inspectors::TracerEip3155}; +use revm::{database_interface::WrapDatabaseAsync, primitives::TxKind, Context}; use std::io::BufWriter; use std::io::Write; use std::sync::Arc; @@ -49,6 +38,8 @@ impl Write for FlushWriter { } } +pub fn inspect_ctx_insp() {} + #[tokio::main] async fn main() -> anyhow::Result<()> { // Set up the HTTP transport which is consumed by the RPC client. @@ -83,31 +74,22 @@ async fn main() -> anyhow::Result<()> { let state_db = WrapDatabaseAsync::new(AlloyDB::new(client, prev_id)).unwrap(); let cache_db: CacheDB<_> = CacheDB::new(state_db); let mut state = StateBuilder::new_with_database(cache_db).build(); - let mut evm = InspectorMainEvm::new( - InspectorContext::new( - Context::builder() - .with_db(&mut state) - .modify_block_chained(|b| { - b.number = block.header.number; - b.beneficiary = block.header.beneficiary; - b.timestamp = block.header.timestamp; - - b.difficulty = block.header.difficulty; - b.gas_limit = block.header.gas_limit; - b.basefee = block.header.base_fee_per_gas.unwrap_or_default(); - }) - .modify_cfg_chained(|c| { - c.chain_id = chain_id; - }), - TracerEip3155::new(Box::new(stdout())), - ), - EthHandler::new( - EthValidation::new(), - EthPreExecution::new(), - EthExecution::<_, _, InspectorEthFrame<_, _, EthPrecompileProvider<_, _>>>::new(), - EthPostExecution::new(), - ), - ); + let mut ctx = Context::builder() + .with_db(&mut state) + .modify_block_chained(|b| { + b.number = block.header.number; + b.beneficiary = block.header.beneficiary; + b.timestamp = block.header.timestamp; + + b.difficulty = block.header.difficulty; + b.gas_limit = block.header.gas_limit; + b.basefee = block.header.base_fee_per_gas.unwrap_or_default(); + }) + .modify_cfg_chained(|c| { + c.chain_id = chain_id; + }); + let mut inspector = TracerEip3155::new(Box::new(stdout())); + let mut ctx = InspectorContext::new(&mut ctx, &mut inspector); let txs = block.transactions.len(); println!("Found {txs} transactions."); @@ -124,7 +106,7 @@ async fn main() -> anyhow::Result<()> { }; for tx in transactions { - evm.context.inner.modify_tx(|etx| { + ctx.inner.modify_tx(|etx| { etx.caller = tx.from; etx.gas_limit = tx.gas_limit(); etx.gas_price = tx.gas_price().unwrap_or(tx.inner.max_fee_per_gas()); @@ -160,9 +142,9 @@ async fn main() -> anyhow::Result<()> { let writer = FlushWriter::new(Arc::clone(&inner)); // Inspect and commit the transaction to the EVM - evm.context.inspector.set_writer(Box::new(writer)); + ctx.inspector.set_writer(Box::new(writer)); - let res = evm.exec_commit(); + let res = inspect_main(&mut ctx); if let Err(error) = res { println!("Got error: {:?}", error); diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index 10d9898388..eb2e620f19 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -9,13 +9,11 @@ use std::{convert::Infallible, fmt::Debug}; use database::InMemoryDB; use inspector::{ - inspector_context::InspectorContext, inspector_handler, inspectors::TracerEip3155, - journal::JournalExt, GetInspector, Inspector, InspectorHandler, + inspect_main, inspector_context::InspectorContext, inspectors::TracerEip3155, + journal::JournalExt, GetInspector, Inspector, }; -use revm::bytecode::Bytecode; -use revm::interpreter::{interpreter::EthInterpreter, CallInputs, CallOutcome, InterpreterResult}; -use revm::primitives::{Log, U256}; use revm::{ + bytecode::Bytecode, context::{BlockEnv, Cfg, CfgEnv, TxEnv}, context_interface::{ host::{SStoreResult, SelfDestructResult}, @@ -25,10 +23,12 @@ use revm::{ }, handler::EthPrecompileProvider, handler_interface::PrecompileProvider, + interpreter::{interpreter::EthInterpreter, CallInputs, CallOutcome, InterpreterResult}, precompile::{Address, HashSet, B256}, + primitives::{Log, U256}, specification::hardfork::SpecId, state::{Account, EvmState, TransientStorage}, - Context, Database, DatabaseCommit, Evm, JournalEntry, JournaledState, + Context, Database, DatabaseCommit, JournalEntry, JournaledState, }; /// Backend for cheatcodes. @@ -212,7 +212,7 @@ impl Journal for Backend { self.journaled_state.depth } - fn finalize(&mut self) -> Result::Error> { + fn finalize(&mut self) -> Self::FinalOutput { let JournaledState { state, transient_storage, @@ -231,7 +231,7 @@ impl Journal for Backend { let state = std::mem::take(state); let logs = std::mem::take(logs); - Ok((state, logs)) + (state, logs) } } @@ -317,17 +317,8 @@ impl DatabaseExt for Backend { BlockT: Block, TxT: Transaction, CfgT: Cfg, - PrecompileT: PrecompileProvider< - Context = InspectorContext< - InspectorT, - InMemoryDB, - Context, - >, - Output = InterpreterResult, - Error = EVMError, - >, { - commit_transaction::(self, env, inspector)?; + commit_transaction::(self, env, inspector)?; self.method_with_inspector_counter += 1; Ok(()) } @@ -348,16 +339,6 @@ impl DatabaseExt for Backend { BlockT, TxT, CfgT, - // Since we can't have a generic precompiles type param as explained in the trait definition, we're using - // concrete type here. - EthPrecompileProvider< - InspectorContext< - TracerEip3155, EthInterpreter>, - InMemoryDB, - Context, - >, - EVMError, - >, >(self, env, inspector)?; self.method_without_inspector_counter += 1; @@ -459,7 +440,7 @@ impl Env { /// Executes a transaction and runs the inspector using the `Backend` as the state. /// Mimics `commit_transaction` -fn commit_transaction( +fn commit_transaction( backend: &mut Backend, env: Env, inspector: InspectorT, @@ -473,15 +454,6 @@ where BlockT: Block, TxT: Transaction, CfgT: Cfg, - PrecompileT: PrecompileProvider< - Context = InspectorContext< - InspectorT, - InMemoryDB, - Context, - >, - Output = InterpreterResult, - Error = EVMError, - >, { // Create new journaled state and backend with the same DB and journaled state as the original for the transaction. // This new backend and state will be discarded after the transaction is done and the changes are applied to the @@ -498,26 +470,13 @@ where error: Ok(()), }; - let inspector_context = InspectorContext::< + let mut inspector_context = InspectorContext::< InspectorT, InMemoryDB, Context, >::new(context, inspector); - let mut evm = Evm::new( - inspector_context, - inspector_handler::< - InspectorContext< - InspectorT, - InMemoryDB, - Context, - >, - EVMError, - PrecompileT, - >(), - ); - - let result = evm.transact()?; + let result = inspect_main(&mut inspector_context)?; // Persist the changes to the original backend. backend.journaled_state.database.commit(result.state); @@ -543,15 +502,6 @@ fn update_state(state: &mut EvmState, db: &mut DB) -> Result<(), D } fn main() -> anyhow::Result<()> { - type InspectorT<'cheatcodes> = &'cheatcodes mut Cheatcodes; - type ErrorT = EVMError; - type InspectorContextT<'cheatcodes> = InspectorContext< - InspectorT<'cheatcodes>, - InMemoryDB, - Context, - >; - type PrecompileT<'cheatcodes> = EthPrecompileProvider, ErrorT>; - let backend = Backend::new(SpecId::LATEST, InMemoryDB::default()); let mut inspector = Cheatcodes::::default(); let env = Env::mainnet(); @@ -564,32 +514,18 @@ fn main() -> anyhow::Result<()> { chain: (), error: Ok(()), }; - let inspector_context = InspectorContext::< - InspectorT<'_>, - InMemoryDB, - Context, - >::new(context, &mut inspector); - let handler = inspector_handler::, ErrorT, PrecompileT<'_>>(); - - let mut evm = Evm::< - ErrorT, - InspectorContextT<'_>, - InspectorHandler, ErrorT, PrecompileT<'_>>, - >::new(inspector_context, handler); + let mut context = InspectorContext::new(context, &mut inspector); - evm.transact()?; + inspect_main(&mut context)?; // Sanity check - assert_eq!(evm.context.inspector.call_count, 2); + assert_eq!(context.inspector.call_count, 2); assert_eq!( - evm.context - .inner - .journaled_state - .method_with_inspector_counter, + context.inner.journaled_state.method_with_inspector_counter, 1 ); assert_eq!( - evm.context + context .inner .journaled_state .method_without_inspector_counter, diff --git a/examples/contract_deployment/src/main.rs b/examples/contract_deployment/src/main.rs index c8cd211f12..3e0309c63c 100644 --- a/examples/contract_deployment/src/main.rs +++ b/examples/contract_deployment/src/main.rs @@ -8,9 +8,8 @@ use revm::{ context::Context, context_interface::result::{ExecutionResult, Output}, database_interface::EmptyDB, - handler::EthHandler, primitives::{hex, Bytes, TxKind, U256}, - EvmCommit, MainEvm, + transact_main, transact_main_commit, }; /// Load number parameter and set to storage with slot 0 @@ -48,18 +47,15 @@ const RUNTIME_BYTECODE: &[u8] = &[opcode::PUSH0, opcode::SLOAD]; fn main() -> anyhow::Result<()> { let param = 0x42; let bytecode: Bytes = [INIT_CODE, RET, RUNTIME_BYTECODE, &[param]].concat().into(); - let mut evm = MainEvm::new( - Context::builder() - .modify_tx_chained(|tx| { - tx.kind = TxKind::Create; - tx.data = bytecode.clone(); - }) - .with_db(CacheDB::::default()), - EthHandler::default(), - ); + let mut ctx = Context::builder() + .modify_tx_chained(|tx| { + tx.kind = TxKind::Create; + tx.data = bytecode.clone(); + }) + .with_db(CacheDB::::default()); println!("bytecode: {}", hex::encode(bytecode)); - let ref_tx = evm.exec_commit()?; + let ref_tx = transact_main_commit(&mut ctx)?; let ExecutionResult::Success { output: Output::Create(_, Some(address)), .. @@ -69,13 +65,13 @@ fn main() -> anyhow::Result<()> { }; println!("Created contract at {address}"); - evm.context.modify_tx(|tx| { + ctx.modify_tx(|tx| { tx.kind = TxKind::Call(address); tx.data = Default::default(); tx.nonce += 1; }); - let result = evm.transact()?; + let result = transact_main(&mut ctx)?; let Some(storage0) = result .state .get(&address) diff --git a/examples/erc20_gas/src/exec.rs b/examples/erc20_gas/src/exec.rs new file mode 100644 index 0000000000..1d8fdc4655 --- /dev/null +++ b/examples/erc20_gas/src/exec.rs @@ -0,0 +1,27 @@ +use crate::handler::Erc20MainetHandler; +use revm::{ + context_interface::{ + result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, ResultAndState}, + DatabaseGetter, + }, + database_interface::{Database, DatabaseCommit}, + handler::handler::{EthContext, EthHandler}, +}; + +pub fn transact_erc20evm>( + ctx: &mut CTX, +) -> Result, EVMError<::Error, InvalidTransaction>> { + Erc20MainetHandler::::new().run(ctx) +} + +pub fn transact_erc20evm_commit< + DB: Database + DatabaseCommit, + CTX: EthContext + DatabaseGetter, +>( + ctx: &mut CTX, +) -> Result, EVMError<::Error, InvalidTransaction>> { + transact_erc20evm(ctx).map(|r| { + ctx.db().commit(r.state); + r.result + }) +} diff --git a/examples/erc20_gas/src/handler.rs b/examples/erc20_gas/src/handler.rs new file mode 100644 index 0000000000..f4b3099807 --- /dev/null +++ b/examples/erc20_gas/src/handler.rs @@ -0,0 +1,189 @@ +use revm::{ + context::Cfg, + context_interface::{ + result::{HaltReason, InvalidTransaction}, + Block, CfgGetter, Journal, Transaction, TransactionType, + }, + handler::{EthContext, EthError, EthFrame, EthHandler, EthPrecompileProvider, FrameContext}, + handler_interface::Frame, + interpreter::{ + interpreter::{EthInstructionProvider, EthInterpreter}, + Host, + }, + precompile::PrecompileErrors, + primitives::U256, + specification::hardfork::SpecId, +}; +use std::cmp::Ordering; + +use crate::{erc_address_storage, token_operation, TOKEN, TREASURY}; + +pub struct Erc20MainetHandler> { + frame_context: FrameContext< + EthPrecompileProvider, + EthInstructionProvider, + >, +} + +impl> Erc20MainetHandler { + pub fn new() -> Self { + Self { + frame_context: FrameContext::new( + EthPrecompileProvider::new(SpecId::LATEST), + EthInstructionProvider::default(), + ), + } + } +} + +impl> Default + for Erc20MainetHandler +{ + fn default() -> Self { + Self::new() + } +} + +impl EthHandler for Erc20MainetHandler +where + CTX: EthContext, + ERROR: EthError, +{ + type Context = CTX; + type Error = ERROR; + type Precompiles = EthPrecompileProvider; + type Instructions = EthInstructionProvider; + type Frame = + EthFrame>; + type HaltReason = HaltReason; + + fn frame_context( + &mut self, + _context: &mut Self::Context, + ) -> ::FrameContext { + FrameContext { + precompiles: self.frame_context.precompiles.clone(), + instructions: self.frame_context.instructions.clone(), + } + } + + fn validate_tx_against_state(&self, context: &mut Self::Context) -> Result<(), Self::Error> { + let caller = context.tx().caller(); + let caller_nonce = context.journal().load_account(caller)?.data.info.nonce; + let _ = context.journal().load_account(TOKEN)?.data.clone(); + + if !context.cfg().is_nonce_check_disabled() { + let tx_nonce = context.tx().nonce(); + let state_nonce = caller_nonce; + match tx_nonce.cmp(&state_nonce) { + Ordering::Less => { + return Err(ERROR::from(InvalidTransaction::NonceTooLow { + tx: tx_nonce, + state: state_nonce, + })) + } + Ordering::Greater => { + return Err(ERROR::from(InvalidTransaction::NonceTooHigh { + tx: tx_nonce, + state: state_nonce, + })) + } + _ => (), + } + } + + let mut balance_check = U256::from(context.tx().gas_limit()) + .checked_mul(U256::from(context.tx().max_fee_per_gas())) + .and_then(|gas_cost| gas_cost.checked_add(context.tx().value())) + .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; + + if context.tx().tx_type() == TransactionType::Eip4844 { + let tx = context.tx(); + let data_fee = tx.calc_max_data_fee(); + balance_check = balance_check + .checked_add(data_fee) + .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; + } + + let account_balance_slot = erc_address_storage(caller); + let account_balance = context + .journal() + .sload(TOKEN, account_balance_slot) + .map(|v| v.data) + .unwrap_or_default(); + + if account_balance < balance_check && !context.cfg().is_balance_check_disabled() { + return Err(InvalidTransaction::LackOfFundForMaxFee { + fee: Box::new(balance_check), + balance: Box::new(account_balance), + } + .into()); + }; + + Ok(()) + } + + fn deduct_caller(&self, context: &mut Self::Context) -> Result<(), Self::Error> { + // load and touch token account + let _ = context.journal().load_account(TOKEN)?.data; + context.journal().touch_account(TOKEN); + + let basefee = context.block().basefee() as u128; + let blob_price = context.block().blob_gasprice().unwrap_or_default(); + let effective_gas_price = context.tx().effective_gas_price(basefee); + + let mut gas_cost = (context.tx().gas_limit() as u128).saturating_mul(effective_gas_price); + + if context.tx().tx_type() == TransactionType::Eip4844 { + let blob_gas = context.tx().total_blob_gas() as u128; + gas_cost = gas_cost.saturating_add(blob_price.saturating_mul(blob_gas)); + } + + let caller = context.tx().caller(); + println!("Deduct caller: {:?} for amount: {gas_cost:?}", caller); + token_operation::(context, caller, TREASURY, U256::from(gas_cost))?; + + Ok(()) + } + + fn reimburse_caller( + &self, + context: &mut Self::Context, + exec_result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { + let basefee = context.block().basefee() as u128; + let caller = context.tx().caller(); + let effective_gas_price = context.tx().effective_gas_price(basefee); + let gas = exec_result.gas(); + + let reimbursement = + effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128); + token_operation::(context, TREASURY, caller, U256::from(reimbursement))?; + + Ok(()) + } + + fn reward_beneficiary( + &self, + context: &mut Self::Context, + exec_result: &mut ::FrameResult, + ) -> Result<(), Self::Error> { + let tx = context.tx(); + let beneficiary = context.block().beneficiary(); + let basefee = context.block().basefee() as u128; + let effective_gas_price = tx.effective_gas_price(basefee); + let gas = exec_result.gas(); + + let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) { + effective_gas_price.saturating_sub(basefee) + } else { + effective_gas_price + }; + + let reward = + coinbase_gas_price.saturating_mul((gas.spent() - gas.refunded() as u64) as u128); + token_operation::(context, TREASURY, beneficiary, U256::from(reward))?; + + Ok(()) + } +} diff --git a/examples/erc20_gas/src/handlers/mod.rs b/examples/erc20_gas/src/handlers/mod.rs deleted file mode 100644 index cc25fb1e21..0000000000 --- a/examples/erc20_gas/src/handlers/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -pub mod post_execution; -pub mod pre_execution; -pub mod validation; - -pub use post_execution::Erc20PostExecution; -pub use pre_execution::Erc20PreExecution; -pub use validation::Erc20Validation; - -use revm::{ - context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context}, - context_interface::result::{EVMError, InvalidTransaction}, - database_interface::Database, - handler::{EthExecution, EthHandler}, - Evm, -}; - -pub type Erc20GasError = EVMError<::Error, InvalidTransaction>; - -pub type Erc20GasContext = Context; - -pub type CustomHandler< - CTX, - ERROR, - VAL = Erc20Validation, - PREEXEC = Erc20PreExecution, - EXEC = EthExecution, - POSTEXEC = Erc20PostExecution, -> = EthHandler; - -pub type CustomEvm = Evm< - Erc20GasError, - Erc20GasContext, - CustomHandler, Erc20GasError>, ->; diff --git a/examples/erc20_gas/src/handlers/post_execution.rs b/examples/erc20_gas/src/handlers/post_execution.rs deleted file mode 100644 index 3335033606..0000000000 --- a/examples/erc20_gas/src/handlers/post_execution.rs +++ /dev/null @@ -1,119 +0,0 @@ -use crate::{token_operation, TREASURY}; -use revm::{ - context::Cfg, - context_interface::{ - result::{HaltReason, HaltReasonTrait, InvalidHeader, InvalidTransaction, ResultAndState}, - Block, JournalDBError, Transaction, TransactionGetter, - }, - handler::{EthPostExecution, EthPostExecutionContext, EthPostExecutionError, FrameResult}, - handler_interface::{InitialAndFloorGas, PostExecutionHandler}, - precompile::PrecompileErrors, - primitives::U256, - specification::hardfork::SpecId, -}; - -pub struct Erc20PostExecution { - inner: EthPostExecution, -} - -impl Erc20PostExecution { - pub fn new() -> Self { - Self { - inner: EthPostExecution::new(), - } - } -} - -impl Default for Erc20PostExecution { - fn default() -> Self { - Self::new() - } -} - -impl PostExecutionHandler for Erc20PostExecution -where - CTX: EthPostExecutionContext, - ERROR: EthPostExecutionError - + From - + From - + From> - + From, - HALTREASON: HaltReasonTrait, -{ - type Context = CTX; - type Error = ERROR; - type ExecResult = FrameResult; - type Output = ResultAndState; - - fn eip7623_check_gas_floor( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - init_and_floor_gas: InitialAndFloorGas, - ) { - self.inner - .eip7623_check_gas_floor(context, exec_result, init_and_floor_gas) - } - - fn refund( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - eip7702_refund: i64, - ) { - self.inner.refund(context, exec_result, eip7702_refund) - } - - fn reimburse_caller( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error> { - let basefee = context.block().basefee() as u128; - let caller = context.tx().caller(); - let effective_gas_price = context.tx().effective_gas_price(basefee); - let gas = exec_result.gas(); - - let reimbursement = - effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128); - token_operation::(context, TREASURY, caller, U256::from(reimbursement))?; - - Ok(()) - } - - fn reward_beneficiary( - &self, - context: &mut Self::Context, - exec_result: &mut Self::ExecResult, - ) -> Result<(), Self::Error> { - let tx = context.tx(); - let beneficiary = context.block().beneficiary(); - let basefee = context.block().basefee() as u128; - let effective_gas_price = tx.effective_gas_price(basefee); - let gas = exec_result.gas(); - - let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) { - effective_gas_price.saturating_sub(basefee) - } else { - effective_gas_price - }; - - let reward = - coinbase_gas_price.saturating_mul((gas.spent() - gas.refunded() as u64) as u128); - token_operation::(context, TREASURY, beneficiary, U256::from(reward))?; - - Ok(()) - } - - fn output( - &self, - context: &mut Self::Context, - result: Self::ExecResult, - ) -> Result { - self.inner.output(context, result) - } - - fn clear(&self, context: &mut Self::Context) { - self.inner.clear(context) - } -} diff --git a/examples/erc20_gas/src/handlers/pre_execution.rs b/examples/erc20_gas/src/handlers/pre_execution.rs deleted file mode 100644 index eef01ee7b1..0000000000 --- a/examples/erc20_gas/src/handlers/pre_execution.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::{token_operation, TREASURY}; -use revm::{ - context_interface::{ - result::InvalidHeader, Block, Transaction, TransactionGetter, TransactionType, - }, - handler::{EthPreExecution, EthPreExecutionContext, EthPreExecutionError}, - handler_interface::PreExecutionHandler, - precompile::PrecompileErrors, - primitives::U256, -}; - -pub struct Erc20PreExecution { - inner: EthPreExecution, -} - -impl Erc20PreExecution { - pub fn new() -> Self { - Self { - inner: EthPreExecution::new(), - } - } -} - -impl Default for Erc20PreExecution { - fn default() -> Self { - Self::new() - } -} - -impl PreExecutionHandler for Erc20PreExecution -where - CTX: EthPreExecutionContext, - ERROR: EthPreExecutionError + From + From, -{ - type Context = CTX; - type Error = ERROR; - - fn load_accounts(&self, context: &mut Self::Context) -> Result<(), Self::Error> { - self.inner.load_accounts(context) - } - - fn apply_eip7702_auth_list(&self, context: &mut Self::Context) -> Result { - self.inner.apply_eip7702_auth_list(context) - } - - fn deduct_caller(&self, context: &mut Self::Context) -> Result<(), Self::Error> { - let basefee = context.block().basefee() as u128; - let blob_price = context.block().blob_gasprice().unwrap_or_default(); - let effective_gas_price = context.tx().effective_gas_price(basefee); - - let mut gas_cost = (context.tx().gas_limit() as u128).saturating_mul(effective_gas_price); - - if context.tx().tx_type() == TransactionType::Eip4844 { - let blob_gas = context.tx().total_blob_gas() as u128; - gas_cost = gas_cost.saturating_add(blob_price.saturating_mul(blob_gas)); - } - - let caller = context.tx().caller(); - token_operation::(context, caller, TREASURY, U256::from(gas_cost))?; - - Ok(()) - } -} diff --git a/examples/erc20_gas/src/handlers/validation.rs b/examples/erc20_gas/src/handlers/validation.rs deleted file mode 100644 index 68b37eb009..0000000000 --- a/examples/erc20_gas/src/handlers/validation.rs +++ /dev/null @@ -1,106 +0,0 @@ -use crate::TOKEN; -use alloy_sol_types::SolValue; -use revm::{ - context::Cfg, - context_interface::{ - result::InvalidTransaction, Journal, Transaction, TransactionGetter, TransactionType, - }, - handler::{EthValidation, EthValidationContext, EthValidationError}, - handler_interface::{InitialAndFloorGas, ValidationHandler}, - primitives::{keccak256, U256}, -}; -use std::cmp::Ordering; - -pub struct Erc20Validation { - inner: EthValidation, -} - -impl Erc20Validation { - pub fn new() -> Self { - Self { - inner: EthValidation::new(), - } - } -} - -impl Default for Erc20Validation { - fn default() -> Self { - Self::new() - } -} - -impl ValidationHandler for Erc20Validation -where - CTX: EthValidationContext, - ERROR: EthValidationError, -{ - type Context = CTX; - type Error = ERROR; - - fn validate_env(&self, context: &Self::Context) -> Result<(), Self::Error> { - self.inner.validate_env(context) - } - - fn validate_tx_against_state(&self, context: &mut Self::Context) -> Result<(), Self::Error> { - let caller = context.tx().caller(); - let caller_nonce = context.journal().load_account(caller)?.data.info.nonce; - let token_account = context.journal().load_account(TOKEN)?.data.clone(); - - if !context.cfg().is_nonce_check_disabled() { - let tx_nonce = context.tx().nonce(); - let state_nonce = caller_nonce; - match tx_nonce.cmp(&state_nonce) { - Ordering::Less => { - return Err(ERROR::from(InvalidTransaction::NonceTooLow { - tx: tx_nonce, - state: state_nonce, - })) - } - Ordering::Greater => { - return Err(ERROR::from(InvalidTransaction::NonceTooHigh { - tx: tx_nonce, - state: state_nonce, - })) - } - _ => (), - } - } - - let mut balance_check = U256::from(context.tx().gas_limit()) - .checked_mul(U256::from(context.tx().max_fee_per_gas())) - .and_then(|gas_cost| gas_cost.checked_add(context.tx().value())) - .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; - - if context.tx().tx_type() == TransactionType::Eip4844 { - let tx = context.tx(); - let data_fee = tx.calc_max_data_fee(); - balance_check = balance_check - .checked_add(data_fee) - .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; - } - - let account_balance_slot: U256 = keccak256((caller, U256::from(3)).abi_encode()).into(); - let account_balance = token_account - .storage - .get(&account_balance_slot) - .expect("Balance slot not found") - .present_value(); - - if account_balance < balance_check && !context.cfg().is_balance_check_disabled() { - return Err(InvalidTransaction::LackOfFundForMaxFee { - fee: Box::new(balance_check), - balance: Box::new(account_balance), - } - .into()); - }; - - Ok(()) - } - - fn validate_initial_tx_gas( - &self, - context: &Self::Context, - ) -> Result { - self.inner.validate_initial_tx_gas(context) - } -} diff --git a/examples/erc20_gas/src/main.rs b/examples/erc20_gas/src/main.rs index ddb372bd68..a018c6876a 100644 --- a/examples/erc20_gas/src/main.rs +++ b/examples/erc20_gas/src/main.rs @@ -5,32 +5,33 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] use alloy_provider::{network::Ethereum, ProviderBuilder, RootProvider}; -use alloy_sol_types::{sol, SolCall, SolValue}; +use alloy_sol_types::SolValue; use alloy_transport_http::Http; -use anyhow::{anyhow, Result}; +use anyhow::Result; use database::{AlloyDB, BlockId, CacheDB}; +use exec::transact_erc20evm_commit; use reqwest::{Client, Url}; use revm::{ context_interface::{ - result::{ExecutionResult, InvalidHeader, InvalidTransaction, Output}, + result::{InvalidHeader, InvalidTransaction}, Journal, JournalDBError, JournalGetter, }, database_interface::WrapDatabaseAsync, - handler::EthExecution, precompile::PrecompileErrors, primitives::{address, keccak256, Address, Bytes, TxKind, U256}, - state::{AccountInfo, EvmStorageSlot}, - Context, EvmCommit, MainEvm, + specification::hardfork::SpecId, + state::AccountInfo, + Context, Database, }; -pub mod handlers; -use handlers::{CustomEvm, CustomHandler, Erc20PostExecution, Erc20PreExecution, Erc20Validation}; +pub mod exec; +pub mod handler; type AlloyCacheDB = CacheDB, Ethereum, RootProvider>>>>; // Constants -pub const TOKEN: Address = address!("1234567890123456789012345678901234567890"); +pub const TOKEN: Address = address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"); pub const TREASURY: Address = address!("0000000000000000000000000000000000000001"); #[tokio::main] @@ -48,35 +49,32 @@ async fn main() -> Result<()> { // Random empty account: To let account_to = address!("21a4B6F62E51e59274b6Be1705c7c68781B87C77"); - let usdc = address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"); - // USDC has 6 decimals let hundred_tokens = U256::from(100_000_000_000_000_000u128); - let balance_slot = keccak256((account, U256::from(3)).abi_encode()).into(); - + let balance_slot = erc_address_storage(account); + println!("Balance slot: {balance_slot}"); cache_db - .insert_account_storage(usdc, balance_slot, hundred_tokens) + .insert_account_storage(TOKEN, balance_slot, hundred_tokens * U256::from(2)) .unwrap(); cache_db.insert_account_info( account, AccountInfo { nonce: 0, - balance: hundred_tokens, + balance: hundred_tokens * U256::from(2), code_hash: keccak256(Bytes::new()), code: None, }, ); - let balance_before = balance_of(usdc, account, &mut cache_db).unwrap(); + let balance_before = balance_of(account, &mut cache_db).unwrap(); + println!("Balance before: {balance_before}"); // Transfer 100 tokens from account to account_to // Magic happens here with custom handlers - transfer(account, account_to, hundred_tokens, usdc, &mut cache_db)?; + transfer(account, account_to, hundred_tokens, &mut cache_db)?; - let balance_after = balance_of(usdc, account, &mut cache_db)?; - - println!("Balance before: {balance_before}"); + let balance_after = balance_of(account, &mut cache_db)?; println!("Balance after: {balance_after}"); Ok(()) @@ -96,14 +94,8 @@ where + From> + From, { - let token_account = context.journal().load_account(TOKEN)?.data; - - let sender_balance_slot: U256 = keccak256((sender, U256::from(3)).abi_encode()).into(); - let sender_balance = token_account - .storage - .get(&sender_balance_slot) - .expect("Balance slot not found") - .present_value(); + let sender_balance_slot = erc_address_storage(sender); + let sender_balance = context.journal().sload(TOKEN, sender_balance_slot)?.data; if sender_balance < amount { return Err(ERROR::from( @@ -112,102 +104,47 @@ where } // Subtract the amount from the sender's balance let sender_new_balance = sender_balance.saturating_sub(amount); - token_account.storage.insert( - sender_balance_slot, - EvmStorageSlot::new_changed(sender_balance, sender_new_balance), - ); + context + .journal() + .sstore(TOKEN, sender_balance_slot, sender_new_balance)?; // Add the amount to the recipient's balance - let recipient_balance_slot: U256 = keccak256((recipient, U256::from(3)).abi_encode()).into(); - let recipient_balance = token_account - .storage - .get(&recipient_balance_slot) - .expect("To balance slot not found") - .present_value(); + let recipient_balance_slot = erc_address_storage(recipient); + let recipient_balance = context.journal().sload(TOKEN, recipient_balance_slot)?.data; + let recipient_new_balance = recipient_balance.saturating_add(amount); - token_account.storage.insert( - recipient_balance_slot, - EvmStorageSlot::new_changed(recipient_balance, recipient_new_balance), - ); + context + .journal() + .sstore(TOKEN, recipient_balance_slot, recipient_new_balance)?; Ok(()) } -fn balance_of(token: Address, address: Address, alloy_db: &mut AlloyCacheDB) -> Result { - sol! { - function balanceOf(address account) public returns (uint256); - } - - let encoded = balanceOfCall { account: address }.abi_encode(); - - let mut evm = MainEvm::new( - Context::builder() - .with_db(alloy_db) - .modify_tx_chained(|tx| { - // 0x1 because calling USDC proxy from zero address fails - tx.caller = address!("0000000000000000000000000000000000000001"); - tx.kind = TxKind::Call(token); - tx.data = encoded.into(); - tx.value = U256::from(0); - }), - CustomHandler::default(), - ); - - let ref_tx = evm.exec_commit().unwrap(); - let value = match ref_tx { - ExecutionResult::Success { - output: Output::Call(value), - .. - } => value, - result => return Err(anyhow!("'balanceOf' execution failed: {result:?}")), - }; - - let balance = ::abi_decode(&value, false)?; - - Ok(balance) +fn balance_of(address: Address, alloy_db: &mut AlloyCacheDB) -> Result { + let slot = erc_address_storage(address); + alloy_db.storage(TOKEN, slot).map_err(From::from) } -fn transfer( - from: Address, - to: Address, - amount: U256, - token: Address, - cache_db: &mut AlloyCacheDB, -) -> Result<()> { - sol! { - function transfer(address to, uint amount) external returns (bool); - } - - let encoded = transferCall { to, amount }.abi_encode(); - - let mut evm = CustomEvm::new( - Context::builder() - .with_db(cache_db) - .modify_tx_chained(|tx| { - tx.caller = from; - tx.kind = TxKind::Call(token); - tx.data = encoded.into(); - tx.value = U256::from(0); - }), - CustomHandler::new( - Erc20Validation::new(), - Erc20PreExecution::new(), - EthExecution::new(), - Erc20PostExecution::new(), - ), - ); - let ref_tx = evm.exec_commit().unwrap(); - let success: bool = match ref_tx { - ExecutionResult::Success { - output: Output::Call(value), - .. - } => ::abi_decode(&value, false)?, - result => return Err(anyhow!("'transfer' execution failed: {result:?}")), - }; - - if !success { - return Err(anyhow!("'transfer' failed")); - } +fn transfer(from: Address, to: Address, amount: U256, cache_db: &mut AlloyCacheDB) -> Result<()> { + let mut ctx = Context::builder() + .with_db(cache_db) + .modify_cfg_chained(|cfg| { + cfg.spec = SpecId::CANCUN; + }) + .modify_tx_chained(|tx| { + tx.caller = from; + tx.kind = TxKind::Call(to); + tx.value = amount; + tx.gas_price = 2; + }) + .modify_block_chained(|b| { + b.basefee = 1; + }); + transact_erc20evm_commit(&mut ctx).unwrap(); Ok(()) } + +pub fn erc_address_storage(address: Address) -> U256 { + keccak256((address, U256::from(4)).abi_encode()).into() +} diff --git a/examples/uniswap_get_reserves/src/main.rs b/examples/uniswap_get_reserves/src/main.rs index 7ab56c7c79..09c07de66d 100644 --- a/examples/uniswap_get_reserves/src/main.rs +++ b/examples/uniswap_get_reserves/src/main.rs @@ -3,19 +3,13 @@ use alloy_eips::BlockId; use alloy_provider::ProviderBuilder; -use alloy_sol_types::sol; -use alloy_sol_types::SolCall; +use alloy_sol_types::{sol, SolCall}; use database::{AlloyDB, CacheDB}; -use revm::database_interface::WrapDatabaseAsync; -use revm::handler::EthHandler; -use revm::Context; -use revm::EvmExec; use revm::{ context_interface::result::{ExecutionResult, Output}, - database_interface::DatabaseRef, - database_interface::EmptyDB, + database_interface::{DatabaseRef, EmptyDB, WrapDatabaseAsync}, primitives::{address, TxKind, U256}, - MainEvm, + transact_main, Context, }; #[tokio::main] @@ -71,25 +65,22 @@ async fn main() -> anyhow::Result<()> { .unwrap(); // Initialise an empty (default) EVM - let mut evm = MainEvm::new( - Context::builder() - .with_db(cache_db) - .modify_tx_chained(|tx| { - // fill in missing bits of env struct - // change that to whatever caller you want to be - tx.caller = address!("0000000000000000000000000000000000000000"); - // account you want to transact with - tx.kind = TxKind::Call(pool_address); - // calldata formed via abigen - tx.data = encoded.into(); - // transaction value in wei - tx.value = U256::from(0); - }), - EthHandler::default(), - ); + let mut ctx = Context::builder() + .with_db(cache_db) + .modify_tx_chained(|tx| { + // fill in missing bits of env struct + // change that to whatever caller you want to be + tx.caller = address!("0000000000000000000000000000000000000000"); + // account you want to transact with + tx.kind = TxKind::Call(pool_address); + // calldata formed via abigen + tx.data = encoded.into(); + // transaction value in wei + tx.value = U256::from(0); + }); // Execute transaction without writing to the DB - let ref_tx = evm.exec().unwrap(); + let ref_tx = transact_main(&mut ctx).unwrap(); // Select ExecutionResult struct let result = ref_tx.result; diff --git a/examples/uniswap_v2_usdc_swap/src/main.rs b/examples/uniswap_v2_usdc_swap/src/main.rs index fd97dc1f8f..8ec72fbcd9 100644 --- a/examples/uniswap_v2_usdc_swap/src/main.rs +++ b/examples/uniswap_v2_usdc_swap/src/main.rs @@ -11,10 +11,9 @@ use reqwest::Client; use revm::{ context_interface::result::{ExecutionResult, Output}, database_interface::WrapDatabaseAsync, - handler::EthHandler, primitives::{address, keccak256, Address, Bytes, TxKind, U256}, state::AccountInfo, - Context, EvmCommit, EvmExec, MainEvm, + transact_main, transact_main_commit, Context, }; use std::ops::Div; @@ -97,20 +96,17 @@ fn balance_of(token: Address, address: Address, alloy_db: &mut AlloyCacheDB) -> let encoded = balanceOfCall { account: address }.abi_encode(); - let mut evm = MainEvm::new( - Context::builder() - .with_db(alloy_db) - .modify_tx_chained(|tx| { - // 0x1 because calling USDC proxy from zero address fails - tx.caller = address!("0000000000000000000000000000000000000001"); - tx.kind = TxKind::Call(token); - tx.data = encoded.into(); - tx.value = U256::from(0); - }), - EthHandler::default(), - ); - - let ref_tx = evm.exec().unwrap(); + let mut ctx = Context::builder() + .with_db(alloy_db) + .modify_tx_chained(|tx| { + // 0x1 because calling USDC proxy from zero address fails + tx.caller = address!("0000000000000000000000000000000000000001"); + tx.kind = TxKind::Call(token); + tx.data = encoded.into(); + tx.value = U256::from(0); + }); + + let ref_tx = transact_main(&mut ctx).unwrap(); let result = ref_tx.result; let value = match result { @@ -144,19 +140,16 @@ async fn get_amount_out( } .abi_encode(); - let mut evm = MainEvm::new( - Context::builder() - .with_db(cache_db) - .modify_tx_chained(|tx| { - tx.caller = address!("0000000000000000000000000000000000000000"); - tx.kind = TxKind::Call(uniswap_v2_router); - tx.data = encoded.into(); - tx.value = U256::from(0); - }), - EthHandler::default(), - ); - - let ref_tx = evm.transact().unwrap(); + let mut ctx = Context::builder() + .with_db(cache_db) + .modify_tx_chained(|tx| { + tx.caller = address!("0000000000000000000000000000000000000000"); + tx.kind = TxKind::Call(uniswap_v2_router); + tx.data = encoded.into(); + tx.value = U256::from(0); + }); + + let ref_tx = transact_main(&mut ctx).unwrap(); let result = ref_tx.result; let value = match result { @@ -179,19 +172,16 @@ fn get_reserves(pair_address: Address, cache_db: &mut AlloyCacheDB) -> Result<(U let encoded = getReservesCall {}.abi_encode(); - let mut evm = MainEvm::new( - Context::builder() - .with_db(cache_db) - .modify_tx_chained(|tx| { - tx.caller = address!("0000000000000000000000000000000000000000"); - tx.kind = TxKind::Call(pair_address); - tx.data = encoded.into(); - tx.value = U256::from(0); - }), - EthHandler::default(), - ); - - let ref_tx = evm.transact().unwrap(); + let mut ctx = Context::builder() + .with_db(cache_db) + .modify_tx_chained(|tx| { + tx.caller = address!("0000000000000000000000000000000000000000"); + tx.kind = TxKind::Call(pair_address); + tx.data = encoded.into(); + tx.value = U256::from(0); + }); + + let ref_tx = transact_main(&mut ctx).unwrap(); let result = ref_tx.result; let value = match result { @@ -230,20 +220,17 @@ fn swap( } .abi_encode(); - let mut evm = MainEvm::new( - Context::builder() - .with_db(cache_db) - .modify_tx_chained(|tx| { - tx.caller = from; - tx.kind = TxKind::Call(pool_address); - tx.data = encoded.into(); - tx.value = U256::from(0); - tx.nonce = 1; - }), - EthHandler::default(), - ); - - let ref_tx = evm.exec_commit().unwrap(); + let mut ctx = Context::builder() + .with_db(cache_db) + .modify_tx_chained(|tx| { + tx.caller = from; + tx.kind = TxKind::Call(pool_address); + tx.data = encoded.into(); + tx.value = U256::from(0); + tx.nonce = 1; + }); + + let ref_tx = transact_main_commit(&mut ctx).unwrap(); match ref_tx { ExecutionResult::Success { .. } => {} @@ -266,19 +253,16 @@ fn transfer( let encoded = transferCall { to, amount }.abi_encode(); - let mut evm = MainEvm::new( - Context::builder() - .with_db(cache_db) - .modify_tx_chained(|tx| { - tx.caller = from; - tx.kind = TxKind::Call(token); - tx.data = encoded.into(); - tx.value = U256::from(0); - }), - EthHandler::default(), - ); - - let ref_tx = evm.exec_commit().unwrap(); + let mut ctx = Context::builder() + .with_db(cache_db) + .modify_tx_chained(|tx| { + tx.caller = from; + tx.kind = TxKind::Call(token); + tx.data = encoded.into(); + tx.value = U256::from(0); + }); + + let ref_tx = transact_main_commit(&mut ctx).unwrap(); let success: bool = match ref_tx { ExecutionResult::Success { output: Output::Call(value), diff --git a/graph.png b/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..4f52c51627781032f2545e54c74f2594540881cd GIT binary patch literal 334974 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�ZW5D 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

v-7UI_5{^Y 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ȝ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 literal 0 HcmV?d00001