From f14e47af4ce9b241a8f342bddb068beb84bf91b6 Mon Sep 17 00:00:00 2001 From: Wodann Date: Tue, 4 Apr 2023 17:17:11 -0500 Subject: [PATCH] refactor: decouple EVMData from Inspector trait --- crates/revm/src/evm.rs | 27 +++++++++++--- crates/revm/src/evm_impl.rs | 39 +++++++++++++++------ crates/revm/src/inspector.rs | 26 ++++++-------- crates/revm/src/inspector/customprinter.rs | 21 +++++------ crates/revm/src/inspector/gas.rs | 38 ++++++++++---------- crates/revm/src/inspector/noop.rs | 4 +-- crates/revm/src/inspector/tracer_eip3155.rs | 29 +++++++-------- crates/revm/src/lib.rs | 4 +-- 8 files changed, 113 insertions(+), 75 deletions(-) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 24b62f51b4..1b068de64c 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -1,4 +1,5 @@ use crate::primitives::{specification, EVMError, EVMResult, Env, ExecutionResult, SpecId}; +use crate::JournaledState; use crate::{ db::{Database, DatabaseCommit, DatabaseRef, RefDBWrapper}, evm_impl::{EVMImpl, Transact}, @@ -61,7 +62,7 @@ impl EVM { Ok(result) } /// Inspect transaction and commit changes to database. - pub fn inspect_commit>( + pub fn inspect_commit>( &mut self, inspector: INSP, ) -> Result> { @@ -84,7 +85,10 @@ impl EVM { } /// Execute transaction with given inspector, without wring to DB. Return change state. - pub fn inspect>(&mut self, mut inspector: INSP) -> EVMResult { + pub fn inspect>( + &mut self, + mut inspector: INSP, + ) -> EVMResult { if let Some(db) = self.db.as_mut() { evm_inner::(&mut self.env, db, &mut inspector).transact() } else { @@ -110,7 +114,7 @@ impl<'a, DB: DatabaseRef> EVM { } /// Execute transaction with given inspector, without wring to DB. Return change state. - pub fn inspect_ref>>( + pub fn inspect_ref>( &'a self, mut inspector: INSP, ) -> EVMResult { @@ -191,7 +195,7 @@ pub fn to_precompile_id(spec_id: SpecId) -> revm_precompile::SpecId { pub fn evm_inner<'a, DB: Database, const INSPECT: bool>( env: &'a mut Env, db: &'a mut DB, - insp: &'a mut dyn Inspector, + insp: &'a mut dyn Inspector, ) -> Box + 'a> { use specification::*; match env.cfg.spec_id { @@ -212,3 +216,18 @@ pub fn evm_inner<'a, DB: Database, const INSPECT: bool>( SpecId::LATEST => create_evm!(LatestSpec, db, env, insp), } } + +/// Trait that exposes internal EVM data. +pub trait EVMData { + /// Returns a mutable reference to the EVM's environment. + fn env(&mut self) -> &mut Env; + + /// Returns a mutable reference to the [`JournaledState`] of the evm. + fn journaled_state(&mut self) -> &mut JournaledState; + + /// Returns a mutable reference to the [`Database`] of the evm. + fn database(&mut self) -> &mut dyn Database; + + /// Returns a mutable reference to the last error, if one occured. + fn error(&mut self) -> &mut Option; +} diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index d759af5dd2..d5eb203433 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,3 +1,4 @@ +use crate::evm::EVMData; use crate::interpreter::{ analysis::to_analysed, gas, instruction_result::SuccessOrHalt, return_ok, return_revert, CallContext, CallInputs, CallScheme, Contract, CreateInputs, CreateScheme, Gas, Host, @@ -19,17 +20,35 @@ use revm_interpreter::gas::initial_tx_gas; use revm_interpreter::MAX_CODE_SIZE; use revm_precompile::{Precompile, Precompiles}; -pub struct EVMData<'a, DB: Database> { - pub env: &'a mut Env, - pub journaled_state: JournaledState, - pub db: &'a mut DB, - pub error: Option, - pub precompiles: Precompiles, +pub(crate) struct EVMDataImpl<'a, DB: Database> { + pub(crate) env: &'a mut Env, + pub(crate) journaled_state: JournaledState, + pub(crate) db: &'a mut DB, + pub(crate) error: Option, + pub(crate) precompiles: Precompiles, +} + +impl<'a, DB: Database> EVMData for EVMDataImpl<'a, DB> { + fn env(&mut self) -> &mut Env { + self.env + } + + fn journaled_state(&mut self) -> &mut JournaledState { + &mut self.journaled_state + } + + fn database(&mut self) -> &mut dyn Database { + self.db + } + + fn error(&mut self) -> &mut Option { + &mut self.error + } } pub struct EVMImpl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> { - data: EVMData<'a, DB>, - inspector: &'a mut dyn Inspector, + data: EVMDataImpl<'a, DB>, + inspector: &'a mut dyn Inspector, _phantomdata: PhantomData, } @@ -227,7 +246,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, pub fn new( db: &'a mut DB, env: &'a mut Env, - inspector: &'a mut dyn Inspector, + inspector: &'a mut dyn Inspector, precompiles: Precompiles, ) -> Self { let journaled_state = if GSPEC::enabled(SpecId::SPURIOUS_DRAGON) { @@ -236,7 +255,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, JournaledState::new_legacy(precompiles.len()) }; Self { - data: EVMData { + data: EVMDataImpl { env, journaled_state, db, diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index cb6d7b5c7e..24f5ec3120 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,6 +1,6 @@ -use crate::evm_impl::EVMData; +use crate::evm::EVMData; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}; -use crate::primitives::{db::Database, Bytes, B160, B256}; +use crate::primitives::{Bytes, B160, B256}; use auto_impl::auto_impl; @@ -26,7 +26,7 @@ pub mod inspectors { } #[auto_impl(&mut, Box)] -pub trait Inspector { +pub trait Inspector { /// Called Before the interpreter is initialized. /// /// If anything other than [InstructionResult::Continue] is returned then execution of the interpreter is @@ -34,7 +34,7 @@ pub trait Inspector { fn initialize_interp( &mut self, _interp: &mut Interpreter, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, ) -> InstructionResult { InstructionResult::Continue } @@ -47,18 +47,14 @@ pub trait Inspector { /// # Example /// /// To get the current opcode, use `interp.current_opcode()`. - fn step( - &mut self, - _interp: &mut Interpreter, - _data: &mut EVMData<'_, DB>, - ) -> InstructionResult { + fn step(&mut self, _interp: &mut Interpreter, _data: &mut dyn EVMData) -> InstructionResult { InstructionResult::Continue } /// Called when a log is emitted. fn log( &mut self, - _evm_data: &mut EVMData<'_, DB>, + _evm_data: &mut dyn EVMData, _address: &B160, _topics: &[B256], _data: &Bytes, @@ -71,7 +67,7 @@ pub trait Inspector { fn step_end( &mut self, _interp: &mut Interpreter, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _eval: InstructionResult, ) -> InstructionResult { InstructionResult::Continue @@ -82,7 +78,7 @@ pub trait Inspector { /// InstructionResulting anything other than [InstructionResult::Continue] overrides the result of the call. fn call( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _inputs: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { (InstructionResult::Continue, Gas::new(0), Bytes::new()) @@ -94,7 +90,7 @@ pub trait Inspector { /// out)`) will alter the result of the call. fn call_end( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _inputs: &CallInputs, remaining_gas: Gas, ret: InstructionResult, @@ -108,7 +104,7 @@ pub trait Inspector { /// InstructionResulting anything other than [InstructionResult::Continue] overrides the result of the creation. fn create( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _inputs: &mut CreateInputs, ) -> (InstructionResult, Option, Gas, Bytes) { ( @@ -125,7 +121,7 @@ pub trait Inspector { /// address, out)`) will alter the result of the create. fn create_end( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _inputs: &CreateInputs, ret: InstructionResult, address: Option, diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index 0d028fecf7..d0f7fffec4 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -1,19 +1,20 @@ //! Custom print inspector, it has step level information of execution. //! It is a great tool if some debugging is needed. //! +use crate::evm::EVMData; use crate::interpreter::{opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}; use crate::primitives::{hex, Bytes, B160}; -use crate::{inspectors::GasInspector, Database, EVMData, Inspector}; +use crate::{inspectors::GasInspector, Inspector}; #[derive(Clone, Default)] pub struct CustomPrintTracer { gas_inspector: GasInspector, } -impl Inspector for CustomPrintTracer { +impl Inspector for CustomPrintTracer { fn initialize_interp( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, ) -> InstructionResult { self.gas_inspector.initialize_interp(interp, data); InstructionResult::Continue @@ -21,7 +22,7 @@ impl Inspector for CustomPrintTracer { // get opcode by calling `interp.contract.opcode(interp.program_counter())`. // all other information can be obtained from interp. - fn step(&mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>) -> InstructionResult { + fn step(&mut self, interp: &mut Interpreter, data: &mut dyn EVMData) -> InstructionResult { let opcode = interp.current_opcode(); let opcode_str = opcode::OPCODE_JUMPMAP[opcode as usize]; @@ -29,7 +30,7 @@ impl Inspector for CustomPrintTracer { println!( "depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data size:{}", - data.journaled_state.depth(), + data.journaled_state().depth(), interp.program_counter(), gas_remaining, gas_remaining, @@ -49,7 +50,7 @@ impl Inspector for CustomPrintTracer { fn step_end( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, eval: InstructionResult, ) -> InstructionResult { self.gas_inspector.step_end(interp, data, eval); @@ -58,7 +59,7 @@ impl Inspector for CustomPrintTracer { fn call_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, inputs: &CallInputs, remaining_gas: Gas, ret: InstructionResult, @@ -71,7 +72,7 @@ impl Inspector for CustomPrintTracer { fn create_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, inputs: &CreateInputs, ret: InstructionResult, address: Option, @@ -85,7 +86,7 @@ impl Inspector for CustomPrintTracer { fn call( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, inputs: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { println!( @@ -101,7 +102,7 @@ impl Inspector for CustomPrintTracer { fn create( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, inputs: &mut CreateInputs, ) -> (InstructionResult, Option, Gas, Bytes) { println!( diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 28ccf87f28..804d23a8d3 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -1,8 +1,9 @@ //! GasIspector. Helper Inspector to calculate gas for others. //! +use crate::evm::EVMData; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult}; -use crate::primitives::{db::Database, Bytes, B160}; -use crate::{evm_impl::EVMData, Inspector}; +use crate::primitives::{Bytes, B160}; +use crate::Inspector; #[allow(dead_code)] #[derive(Clone, Copy, Debug, Default)] @@ -21,12 +22,12 @@ impl GasInspector { } } -impl Inspector for GasInspector { +impl Inspector for GasInspector { #[cfg(not(feature = "no_gas_measuring"))] fn initialize_interp( &mut self, interp: &mut crate::interpreter::Interpreter, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, ) -> InstructionResult { self.gas_remaining = interp.gas.limit(); InstructionResult::Continue @@ -39,7 +40,7 @@ impl Inspector for GasInspector { fn step( &mut self, _interp: &mut crate::interpreter::Interpreter, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, ) -> InstructionResult { InstructionResult::Continue } @@ -48,7 +49,7 @@ impl Inspector for GasInspector { fn step_end( &mut self, interp: &mut crate::interpreter::Interpreter, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _eval: InstructionResult, ) -> InstructionResult { let last_gas = self.gas_remaining; @@ -63,7 +64,7 @@ impl Inspector for GasInspector { fn call_end( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _inputs: &CallInputs, mut remaining_gas: Gas, ret: InstructionResult, @@ -80,7 +81,7 @@ impl Inspector for GasInspector { fn create_end( &mut self, - _data: &mut EVMData<'_, DB>, + _data: &mut dyn EVMData, _inputs: &CreateInputs, ret: InstructionResult, address: Option, @@ -94,13 +95,14 @@ impl Inspector for GasInspector { #[cfg(test)] mod tests { use crate::db::BenchmarkDB; + use crate::evm::EVMData; use crate::interpreter::{ opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, OpCode, }; use crate::primitives::{ hex_literal::hex, Bytecode, Bytes, ResultAndState, TransactTo, B160, B256, }; - use crate::{inspectors::GasInspector, Database, EVMData, Inspector}; + use crate::{inspectors::GasInspector, Inspector}; #[derive(Default, Debug)] struct StackInspector { @@ -109,11 +111,11 @@ mod tests { gas_remaining_steps: Vec<(usize, u64)>, } - impl Inspector for StackInspector { + impl Inspector for StackInspector { fn initialize_interp( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, ) -> InstructionResult { self.gas_inspector.initialize_interp(interp, data); InstructionResult::Continue @@ -122,7 +124,7 @@ mod tests { fn step( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, ) -> InstructionResult { self.pc = interp.program_counter(); self.gas_inspector.step(interp, data); @@ -131,7 +133,7 @@ mod tests { fn log( &mut self, - evm_data: &mut EVMData<'_, DB>, + evm_data: &mut dyn EVMData, address: &B160, topics: &[B256], data: &Bytes, @@ -142,7 +144,7 @@ mod tests { fn step_end( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, eval: InstructionResult, ) -> InstructionResult { self.gas_inspector.step_end(interp, data, eval); @@ -153,7 +155,7 @@ mod tests { fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { self.gas_inspector.call(data, call); @@ -167,7 +169,7 @@ mod tests { fn call_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, inputs: &CallInputs, remaining_gas: Gas, ret: InstructionResult, @@ -180,7 +182,7 @@ mod tests { fn create( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, call: &mut CreateInputs, ) -> (InstructionResult, Option, Gas, Bytes) { self.gas_inspector.create(data, call); @@ -195,7 +197,7 @@ mod tests { fn create_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, inputs: &CreateInputs, status: InstructionResult, address: Option, diff --git a/crates/revm/src/inspector/noop.rs b/crates/revm/src/inspector/noop.rs index 63a6014eb1..d43fe9412c 100644 --- a/crates/revm/src/inspector/noop.rs +++ b/crates/revm/src/inspector/noop.rs @@ -1,8 +1,8 @@ //! Dummy NoOp Inspector, helpful as standalone replacement. -use crate::{Database, Inspector}; +use crate::Inspector; #[derive(Clone, Copy)] pub struct NoOpInspector(); -impl Inspector for NoOpInspector {} +impl Inspector for NoOpInspector {} diff --git a/crates/revm/src/inspector/tracer_eip3155.rs b/crates/revm/src/inspector/tracer_eip3155.rs index 463fd3ce4a..baf6851d9b 100644 --- a/crates/revm/src/inspector/tracer_eip3155.rs +++ b/crates/revm/src/inspector/tracer_eip3155.rs @@ -1,9 +1,10 @@ //! Inspector that support tracing of EIP-3155 +use crate::evm::EVMData; use crate::inspectors::GasInspector; use crate::interpreter::{CallInputs, CreateInputs, Gas, InstructionResult}; -use crate::primitives::{db::Database, hex, Bytes, B160}; -use crate::{evm_impl::EVMData, Inspector}; +use crate::primitives::{hex, Bytes, B160}; +use crate::Inspector; use revm_interpreter::primitives::U256; use revm_interpreter::{opcode, Interpreter, Memory, Stack}; use serde_json::json; @@ -46,11 +47,11 @@ impl TracerEip3155 { } } -impl Inspector for TracerEip3155 { +impl Inspector for TracerEip3155 { fn initialize_interp( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, ) -> InstructionResult { self.gas_inspector.initialize_interp(interp, data); InstructionResult::Continue @@ -58,7 +59,7 @@ impl Inspector for TracerEip3155 { // get opcode by calling `interp.contract.opcode(interp.program_counter())`. // all other information can be obtained from interp. - fn step(&mut self, interp: &mut Interpreter, data: &mut EVMData<'_, DB>) -> InstructionResult { + fn step(&mut self, interp: &mut Interpreter, data: &mut dyn EVMData) -> InstructionResult { self.gas_inspector.step(interp, data); self.stack = interp.stack.clone(); self.pc = interp.program_counter(); @@ -72,7 +73,7 @@ impl Inspector for TracerEip3155 { fn step_end( &mut self, interp: &mut Interpreter, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, eval: InstructionResult, ) -> InstructionResult { self.gas_inspector.step_end(interp, data, eval); @@ -81,22 +82,22 @@ impl Inspector for TracerEip3155 { return InstructionResult::Continue; }; - self.print_log_line(data.journaled_state.depth()); + self.print_log_line(data.journaled_state().depth()); InstructionResult::Continue } fn call( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, _inputs: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { - self.print_log_line(data.journaled_state.depth()); + self.print_log_line(data.journaled_state().depth()); (InstructionResult::Continue, Gas::new(0), Bytes::new()) } fn call_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, inputs: &CallInputs, remaining_gas: Gas, ret: InstructionResult, @@ -106,7 +107,7 @@ impl Inspector for TracerEip3155 { .call_end(data, inputs, remaining_gas, ret, out.clone()); // self.log_step(interp, data, is_static, eval); self.skip = true; - if data.journaled_state.depth() == 0 { + if data.journaled_state().depth() == 0 { let log_line = json!({ //stateroot "output": format!("0x{}", hex::encode(out.as_ref())), @@ -123,10 +124,10 @@ impl Inspector for TracerEip3155 { fn create( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, _inputs: &mut CreateInputs, ) -> (InstructionResult, Option, Gas, Bytes) { - self.print_log_line(data.journaled_state.depth()); + self.print_log_line(data.journaled_state().depth()); ( InstructionResult::Continue, None, @@ -137,7 +138,7 @@ impl Inspector for TracerEip3155 { fn create_end( &mut self, - data: &mut EVMData<'_, DB>, + data: &mut dyn EVMData, inputs: &CreateInputs, ret: InstructionResult, address: Option, diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 0e8ba11c2d..55df75d58d 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -20,8 +20,8 @@ pub type DummyStateDB = InMemoryDB; pub use db::{CacheState, StateBuilder, TransitionAccount, TransitionState}; pub use db::{Database, DatabaseCommit, InMemoryDB, State}; -pub use evm::{evm_inner, new, to_precompile_id, EVM}; -pub use evm_impl::{EVMData, EVMImpl, Transact}; +pub use evm::{evm_inner, new, to_precompile_id, EVMData, EVM}; +pub use evm_impl::{EVMImpl, Transact}; pub use journaled_state::{is_precompile, JournalCheckpoint, JournalEntry, JournaledState}; // reexport `revm_precompiles`