diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index cb7d776e8a..5af567bbfc 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -1,6 +1,6 @@ use clap::Parser; use database::BenchmarkDB; -use inspector::{inspector_handler, inspectors::TracerEip3155, InspectorContext, InspectorMainEvm}; +use inspector::{inspector_handler, inspectors::TracerEip3155, inspector_context::InspectorContext, InspectorMainEvm}; use revm::{ bytecode::{Bytecode, BytecodeDecodeError}, handler::EthHandler, diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index bfdc5c0ae3..b7bd77cbf4 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -4,7 +4,7 @@ use super::{ }; use database::State; use indicatif::{ProgressBar, ProgressDrawTarget}; -use inspector::{inspector_handler, inspectors::TracerEip3155, InspectorContext, InspectorMainEvm}; +use inspector::{inspector_handler, inspectors::TracerEip3155, inspector_context::InspectorContext, InspectorMainEvm}; use revm::{ bytecode::Bytecode, context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv}, diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index e4affa64a0..2cc9959417 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -34,6 +34,8 @@ use revm::{ }; use std::{rc::Rc, vec::Vec}; +use crate::{inspector_context::InspectorContext, inspector_frame::InspectorEthFrame, journal::{JournalExt, JournalExtGetter}}; + /// EVM [Interpreter] callbacks. #[auto_impl(&mut, Box)] pub trait Inspector { @@ -223,305 +225,6 @@ impl GetInspector for INSP { } } -/// EVM context contains data that EVM needs for execution. -#[derive_where(Clone, Debug; INSP, BLOCK, CFG, CHAIN, TX, DB,JOURNAL, ::Error)] -pub struct InspectorContext< - INSP, - BLOCK = BlockEnv, - TX = TxEnv, - CFG = CfgEnv, - DB: Database = EmptyDB, - JOURNAL: Journal = JournaledState, - CHAIN = (), -> { - pub inner: Context, - pub inspector: INSP, - pub frame_input_stack: Vec, -} - -impl< - INSP, - BLOCK: Block, - TX: Transaction, - CFG: Cfg, - DB: Database, - JOURNAL: Journal, - CHAIN, - > InspectorContext -{ - pub fn new(inner: Context, inspector: INSP) -> Self { - Self { - inner, - inspector, - frame_input_stack: Vec::new(), - } - } -} - -impl< - INSP: GetInspector, - BLOCK: Block, - TX: Transaction, - CFG: Cfg, - DB: Database, - JOURNAL: Journal, - CHAIN, - > Host for InspectorContext -{ - type BLOCK = BLOCK; - type TX = TX; - type CFG = CFG; - - fn tx(&self) -> &Self::TX { - &self.inner.tx - } - - fn block(&self) -> &Self::BLOCK { - &self.inner.block - } - - fn cfg(&self) -> &Self::CFG { - &self.inner.cfg - } - - fn block_hash(&mut self, requested_number: u64) -> Option { - self.inner.block_hash(requested_number) - } - - fn load_account_delegated(&mut self, address: Address) -> Option { - self.inner.load_account_delegated(address) - } - - fn balance(&mut self, address: Address) -> Option> { - self.inner.balance(address) - } - - fn code(&mut self, address: Address) -> Option> { - // TODO : Remove duplicated function name. - as Host>::code(&mut self.inner, address) - } - - fn code_hash(&mut self, address: Address) -> Option> { - as Host>::code_hash(&mut self.inner, address) - } - - fn sload(&mut self, address: Address, index: U256) -> Option> { - self.inner.sload(address, index) - } - - fn sstore( - &mut self, - address: Address, - index: U256, - value: U256, - ) -> Option> { - self.inner.sstore(address, index, value) - } - - fn tload(&mut self, address: Address, index: U256) -> U256 { - self.inner.tload(address, index) - } - - fn tstore(&mut self, address: Address, index: U256, value: U256) { - self.inner.tstore(address, index, value) - } - - fn log(&mut self, log: Log) { - self.inner.log(log); - } - - fn selfdestruct( - &mut self, - address: Address, - target: Address, - ) -> Option> { - self.inner.selfdestruct(address, target) - } -} - -impl, CHAIN> InspectorCtx - for InspectorContext -where - INSP: GetInspector< - Inspector: Inspector< - Context = Context, - InterpreterTypes = EthInterpreter, - >, - >, -{ - type IT = EthInterpreter<()>; - - fn step(&mut self, interp: &mut Interpreter) { - self.inspector.get_inspector().step(interp, &mut self.inner); - } - - fn step_end(&mut self, interp: &mut Interpreter) { - self.inspector - .get_inspector() - .step_end(interp, &mut self.inner); - } - - fn initialize_interp(&mut self, interp: &mut Interpreter) { - self.inspector - .get_inspector() - .initialize_interp(interp, &mut self.inner); - } - fn inspector_log(&mut self, interp: &mut Interpreter, log: &Log) { - self.inspector - .get_inspector() - .log(interp, &mut self.inner, log); - } - - fn frame_start(&mut self, frame_input: &mut FrameInput) -> Option { - let insp = self.inspector.get_inspector(); - let context = &mut self.inner; - match frame_input { - FrameInput::Call(i) => { - if let Some(output) = insp.call(context, i) { - return Some(FrameResult::Call(output)); - } - } - FrameInput::Create(i) => { - if let Some(output) = insp.create(context, i) { - return Some(FrameResult::Create(output)); - } - } - FrameInput::EOFCreate(i) => { - if let Some(output) = insp.eofcreate(context, i) { - return Some(FrameResult::EOFCreate(output)); - } - } - } - self.frame_input_stack.push(frame_input.clone()); - None - } - - fn frame_end(&mut self, frame_output: &mut FrameResult) { - let insp = self.inspector.get_inspector(); - let context = &mut self.inner; - let frame_input = self.frame_input_stack.pop().expect("Frame pushed"); - match frame_output { - FrameResult::Call(outcome) => { - let FrameInput::Call(i) = frame_input else { - panic!("FrameInput::Call expected"); - }; - insp.call_end(context, &i, outcome); - } - FrameResult::Create(outcome) => { - let FrameInput::Create(i) = frame_input else { - panic!("FrameInput::Create expected"); - }; - insp.create_end(context, &i, outcome); - } - FrameResult::EOFCreate(outcome) => { - let FrameInput::EOFCreate(i) = frame_input else { - panic!("FrameInput::EofCreate expected"); - }; - insp.eofcreate_end(context, &i, outcome); - } - } - } - - fn inspector_selfdestruct(&mut self, contract: Address, target: Address, value: U256) { - self.inspector - .get_inspector() - .selfdestruct(contract, target, value) - } -} - -impl, CHAIN> CfgGetter - for InspectorContext -{ - type Cfg = CFG; - - fn cfg(&self) -> &Self::Cfg { - &self.inner.cfg - } -} - -impl, CHAIN> JournalStateGetter - for InspectorContext -{ - type Journal = JOURNAL; - - fn journal(&mut self) -> &mut Self::Journal { - &mut self.inner.journaled_state - } -} - -impl, CHAIN> DatabaseGetter - for InspectorContext -{ - type Database = DB; - - fn db(&mut self) -> &mut Self::Database { - self.inner.journaled_state.db_mut() - } -} - -impl, CHAIN> - ErrorGetter for InspectorContext -{ - type Error = EVMError; - - fn take_error(&mut self) -> Result<(), Self::Error> { - core::mem::replace(&mut self.inner.error, Ok(())).map_err(EVMError::Database) - } -} - -impl, CHAIN> - TransactionGetter for InspectorContext -{ - type Transaction = TX; - - fn tx(&self) -> &Self::Transaction { - &self.inner.tx - } -} - -impl, CHAIN> - TransactionSetter for InspectorContext -{ - fn set_tx(&mut self, tx: ::Transaction) { - self.inner.tx = tx; - } -} - -impl, CHAIN> BlockGetter - for InspectorContext -{ - type Block = BLOCK; - - fn block(&self) -> &Self::Block { - &self.inner.block - } -} - -impl, CHAIN> BlockSetter - for InspectorContext -{ - fn set_block(&mut self, block: ::Block) { - self.inner.block = block; - } -} - -impl< - INSP, - BLOCK: Block, - TX, - CFG, - DB: Database, - JOURNAL: Journal + JournalExt, - CHAIN, - > JournalExtGetter for InspectorContext -{ - type JournalExt = JOURNAL; - - fn journal_ext(&self) -> &Self::JournalExt { - &self.inner.journaled_state - } -} - #[derive(Clone)] pub struct InspectorInstruction { pub instruction: fn(&mut Interpreter, &mut HOST), @@ -575,29 +278,6 @@ where } } -pub trait JournalExt { - fn logs(&self) -> &[Log]; - - fn last_journal(&self) -> &[JournalEntry]; -} - -impl JournalExt for JournaledState { - fn logs(&self) -> &[Log] { - &self.logs - } - - fn last_journal(&self) -> &[JournalEntry] { - self.journal.last().expect("Journal is never empty") - } -} - -#[auto_impl(&, &mut, Box, Arc)] -pub trait JournalExtGetter { - type JournalExt: JournalExt; - - fn journal_ext(&self) -> &Self::JournalExt; -} - impl InstructionProvider for InspectorInstructionProvider where WIRE: InterpreterTypes, @@ -700,99 +380,7 @@ where } } -pub struct InspectorEthFrame -where - CTX: Host, -{ - // 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>, - >, -} - -impl Frame for InspectorEthFrame -where - CTX: TransactionGetter - + ErrorGetter - + BlockGetter - + JournalStateGetter - + CfgGetter - + JournalExtGetter - + Host - + InspectorCtx, - ERROR: From> + From, - PRECOMPILE: PrecompileProvider, -{ - type Context = CTX; - type Error = ERROR; - type FrameInit = FrameInput; - type FrameResult = FrameResult; - - fn init_first( - context: &mut Self::Context, - mut frame_input: Self::FrameInit, - ) -> Result, Self::Error> { - if let Some(output) = context.frame_start(&mut frame_input) { - return Ok(FrameOrResultGen::Result(output)); - } - let mut ret = EthFrame::init_first(context, frame_input) - .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })); - - match &mut ret { - Ok(FrameOrResultGen::Result(res)) => { - context.frame_end(res); - } - Ok(FrameOrResultGen::Frame(frame)) => { - context.initialize_interp(&mut frame.eth_frame.interpreter); - } - _ => (), - } - - ret - } - - fn init( - &self, - context: &mut Self::Context, - mut frame_input: Self::FrameInit, - ) -> Result, Self::Error> { - if let Some(output) = context.frame_start(&mut frame_input) { - return Ok(FrameOrResultGen::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); - } - - // TODO : Handle last frame_end. MAKE a separate function for `last_return_result`. - ret - } - - fn run( - &mut self, - context: &mut Self::Context, - ) -> Result, Self::Error> { - self.eth_frame.run(context) - } - - fn return_result( - &mut self, - context: &mut Self::Context, - mut result: Self::FrameResult, - ) -> Result<(), Self::Error> { - context.frame_end(&mut result); - self.eth_frame.return_result(context, result) - } -} pub type InspCtxType< INSP, diff --git a/crates/inspector/src/inspector_context.rs b/crates/inspector/src/inspector_context.rs new file mode 100644 index 0000000000..c195231d78 --- /dev/null +++ b/crates/inspector/src/inspector_context.rs @@ -0,0 +1,340 @@ + +use auto_impl::auto_impl; +use core::mem::MaybeUninit; +use derive_where::derive_where; +use revm::{ + bytecode::opcode::OpCode, + context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv, Cfg, JournaledState}, + context_interface::{ + block::BlockSetter, + journaled_state::{AccountLoad, Eip7702CodeLoad}, + result::EVMError, + transaction::TransactionSetter, + Block, BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, Journal, JournalStateGetter, + JournalStateGetterDBError, Transaction, TransactionGetter, + }, + database_interface::{Database, EmptyDB}, + handler::{ + EthExecution, EthFrame, EthHandler, EthPostExecution, EthPreExecution, + EthPrecompileProvider, EthValidation, FrameResult, + }, + handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}, + interpreter::{ + instructions::host::{log, selfdestruct}, + interpreter::{EthInterpreter, InstructionProvider}, + interpreter_types::{Jumps, LoopControl}, + table::{self, CustomInstruction}, + CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, FrameInput, Host, + Instruction, InstructionResult, Interpreter, InterpreterTypes, SStoreResult, + SelfDestructResult, StateLoad, + }, + precompile::PrecompileErrors, + primitives::{Address, Bytes, Log, B256, U256}, + specification::hardfork::SpecId, + Context, Error, Evm, JournalEntry, +}; +use std::{rc::Rc, vec::Vec}; + +use crate::{GetInspector, Inspector, InspectorCtx}; +use crate::journal::{ JournalExt, JournalExtGetter}; + +/// EVM context contains data that EVM needs for execution. +#[derive_where(Clone, Debug; INSP, BLOCK, CFG, CHAIN, TX, DB,JOURNAL, ::Error)] +pub struct InspectorContext< + INSP, + BLOCK = BlockEnv, + TX = TxEnv, + CFG = CfgEnv, + DB: Database = EmptyDB, + JOURNAL: Journal = JournaledState, + CHAIN = (), +> { + pub inner: Context, + pub inspector: INSP, + pub frame_input_stack: Vec, +} + + +impl< + INSP, + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal, + CHAIN, + > InspectorContext +{ + pub fn new(inner: Context, inspector: INSP) -> Self { + Self { + inner, + inspector, + frame_input_stack: Vec::new(), + } + } +} + +impl< + INSP: GetInspector, + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal, + CHAIN, + > Host for InspectorContext +{ + type BLOCK = BLOCK; + type TX = TX; + type CFG = CFG; + + fn tx(&self) -> &Self::TX { + &self.inner.tx + } + + fn block(&self) -> &Self::BLOCK { + &self.inner.block + } + + fn cfg(&self) -> &Self::CFG { + &self.inner.cfg + } + + fn block_hash(&mut self, requested_number: u64) -> Option { + self.inner.block_hash(requested_number) + } + + fn load_account_delegated(&mut self, address: Address) -> Option { + self.inner.load_account_delegated(address) + } + + fn balance(&mut self, address: Address) -> Option> { + self.inner.balance(address) + } + + fn code(&mut self, address: Address) -> Option> { + // TODO : Remove duplicated function name. + as Host>::code(&mut self.inner, address) + } + + fn code_hash(&mut self, address: Address) -> Option> { + as Host>::code_hash(&mut self.inner, address) + } + + fn sload(&mut self, address: Address, index: U256) -> Option> { + self.inner.sload(address, index) + } + + fn sstore( + &mut self, + address: Address, + index: U256, + value: U256, + ) -> Option> { + self.inner.sstore(address, index, value) + } + + fn tload(&mut self, address: Address, index: U256) -> U256 { + self.inner.tload(address, index) + } + + fn tstore(&mut self, address: Address, index: U256, value: U256) { + self.inner.tstore(address, index, value) + } + + fn log(&mut self, log: Log) { + self.inner.log(log); + } + + fn selfdestruct( + &mut self, + address: Address, + target: Address, + ) -> Option> { + self.inner.selfdestruct(address, target) + } +} + + +impl, CHAIN> InspectorCtx + for InspectorContext +where + INSP: GetInspector< + Inspector: Inspector< + Context = Context, + InterpreterTypes = EthInterpreter, + >, + >, +{ + type IT = EthInterpreter<()>; + + fn step(&mut self, interp: &mut Interpreter) { + self.inspector.get_inspector().step(interp, &mut self.inner); + } + + fn step_end(&mut self, interp: &mut Interpreter) { + self.inspector + .get_inspector() + .step_end(interp, &mut self.inner); + } + + fn initialize_interp(&mut self, interp: &mut Interpreter) { + self.inspector + .get_inspector() + .initialize_interp(interp, &mut self.inner); + } + fn inspector_log(&mut self, interp: &mut Interpreter, log: &Log) { + self.inspector + .get_inspector() + .log(interp, &mut self.inner, log); + } + + fn frame_start(&mut self, frame_input: &mut FrameInput) -> Option { + let insp = self.inspector.get_inspector(); + let context = &mut self.inner; + match frame_input { + FrameInput::Call(i) => { + if let Some(output) = insp.call(context, i) { + return Some(FrameResult::Call(output)); + } + } + FrameInput::Create(i) => { + if let Some(output) = insp.create(context, i) { + return Some(FrameResult::Create(output)); + } + } + FrameInput::EOFCreate(i) => { + if let Some(output) = insp.eofcreate(context, i) { + return Some(FrameResult::EOFCreate(output)); + } + } + } + self.frame_input_stack.push(frame_input.clone()); + None + } + + fn frame_end(&mut self, frame_output: &mut FrameResult) { + let insp = self.inspector.get_inspector(); + let context = &mut self.inner; + let frame_input = self.frame_input_stack.pop().expect("Frame pushed"); + match frame_output { + FrameResult::Call(outcome) => { + let FrameInput::Call(i) = frame_input else { + panic!("FrameInput::Call expected"); + }; + insp.call_end(context, &i, outcome); + } + FrameResult::Create(outcome) => { + let FrameInput::Create(i) = frame_input else { + panic!("FrameInput::Create expected"); + }; + insp.create_end(context, &i, outcome); + } + FrameResult::EOFCreate(outcome) => { + let FrameInput::EOFCreate(i) = frame_input else { + panic!("FrameInput::EofCreate expected"); + }; + insp.eofcreate_end(context, &i, outcome); + } + } + } + + fn inspector_selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + self.inspector + .get_inspector() + .selfdestruct(contract, target, value) + } +} + +impl, CHAIN> CfgGetter + for InspectorContext +{ + type Cfg = CFG; + + fn cfg(&self) -> &Self::Cfg { + &self.inner.cfg + } +} + +impl, CHAIN> JournalStateGetter + for InspectorContext +{ + type Journal = JOURNAL; + + fn journal(&mut self) -> &mut Self::Journal { + &mut self.inner.journaled_state + } +} + +impl, CHAIN> DatabaseGetter + for InspectorContext +{ + type Database = DB; + + fn db(&mut self) -> &mut Self::Database { + self.inner.journaled_state.db_mut() + } +} + +impl, CHAIN> + ErrorGetter for InspectorContext +{ + type Error = EVMError; + + fn take_error(&mut self) -> Result<(), Self::Error> { + core::mem::replace(&mut self.inner.error, Ok(())).map_err(EVMError::Database) + } +} + +impl, CHAIN> + TransactionGetter for InspectorContext +{ + type Transaction = TX; + + fn tx(&self) -> &Self::Transaction { + &self.inner.tx + } +} + +impl, CHAIN> + TransactionSetter for InspectorContext +{ + fn set_tx(&mut self, tx: ::Transaction) { + self.inner.tx = tx; + } +} + +impl, CHAIN> BlockGetter + for InspectorContext +{ + type Block = BLOCK; + + fn block(&self) -> &Self::Block { + &self.inner.block + } +} + +impl, CHAIN> BlockSetter + for InspectorContext +{ + fn set_block(&mut self, block: ::Block) { + self.inner.block = block; + } +} + +impl< + INSP, + BLOCK: Block, + TX, + CFG, + DB: Database, + JOURNAL: Journal + JournalExt, + CHAIN, + > JournalExtGetter for InspectorContext +{ + type JournalExt = JOURNAL; + + fn journal_ext(&self) -> &Self::JournalExt { + &self.inner.journaled_state + } +} \ No newline at end of file diff --git a/crates/inspector/src/inspector_frame.rs b/crates/inspector/src/inspector_frame.rs new file mode 100644 index 0000000000..bdb9ffe588 --- /dev/null +++ b/crates/inspector/src/inspector_frame.rs @@ -0,0 +1,132 @@ + +use auto_impl::auto_impl; +use core::mem::MaybeUninit; +use derive_where::derive_where; +use revm::{ + bytecode::opcode::OpCode, + context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv, Cfg, JournaledState}, + context_interface::{ + block::BlockSetter, + journaled_state::{AccountLoad, Eip7702CodeLoad}, + result::EVMError, + transaction::TransactionSetter, + Block, BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, Journal, JournalStateGetter, + JournalStateGetterDBError, Transaction, TransactionGetter, + }, + database_interface::{Database, EmptyDB}, + handler::{ + EthExecution, EthFrame, EthHandler, EthPostExecution, EthPreExecution, + EthPrecompileProvider, EthValidation, FrameResult, + }, + handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}, + interpreter::{ + instructions::host::{log, selfdestruct}, + interpreter::{EthInterpreter, InstructionProvider}, + interpreter_types::{Jumps, LoopControl}, + table::{self, CustomInstruction}, + CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, FrameInput, Host, + Instruction, InstructionResult, Interpreter, InterpreterTypes, SStoreResult, + SelfDestructResult, StateLoad, + }, + precompile::PrecompileErrors, + primitives::{Address, Bytes, Log, B256, U256}, + specification::hardfork::SpecId, + Context, Error, Evm, JournalEntry, +}; +use std::{rc::Rc, vec::Vec}; + +use crate::{journal::JournalExtGetter, InspectorCtx, InspectorInstructionProvider}; + +pub struct InspectorEthFrame +where + CTX: Host, +{ + // 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>, + >, +} + +impl Frame for InspectorEthFrame +where + CTX: TransactionGetter + + ErrorGetter + + BlockGetter + + JournalStateGetter + + CfgGetter + + JournalExtGetter + + Host + + InspectorCtx, + ERROR: From> + From, + PRECOMPILE: PrecompileProvider, +{ + type Context = CTX; + type Error = ERROR; + type FrameInit = FrameInput; + type FrameResult = FrameResult; + + fn init_first( + context: &mut Self::Context, + mut frame_input: Self::FrameInit, + ) -> Result, Self::Error> { + if let Some(output) = context.frame_start(&mut frame_input) { + return Ok(FrameOrResultGen::Result(output)); + } + let mut ret = EthFrame::init_first(context, frame_input) + .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })); + + match &mut ret { + Ok(FrameOrResultGen::Result(res)) => { + context.frame_end(res); + } + Ok(FrameOrResultGen::Frame(frame)) => { + context.initialize_interp(&mut frame.eth_frame.interpreter); + } + _ => (), + } + + ret + } + + fn init( + &self, + context: &mut Self::Context, + mut frame_input: Self::FrameInit, + ) -> Result, Self::Error> { + if let Some(output) = context.frame_start(&mut frame_input) { + return Ok(FrameOrResultGen::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); + } + + // TODO : Handle last frame_end. MAKE a separate function for `last_return_result`. + + ret + } + + fn run( + &mut self, + context: &mut Self::Context, + ) -> Result, Self::Error> { + self.eth_frame.run(context) + } + + fn return_result( + &mut self, + context: &mut Self::Context, + mut result: Self::FrameResult, + ) -> Result<(), Self::Error> { + context.frame_end(&mut result); + self.eth_frame.return_result(context, result) + } +} \ No newline at end of file diff --git a/crates/inspector/src/journal.rs b/crates/inspector/src/journal.rs new file mode 100644 index 0000000000..b571544a96 --- /dev/null +++ b/crates/inspector/src/journal.rs @@ -0,0 +1,60 @@ + +use auto_impl::auto_impl; +use core::mem::MaybeUninit; +use derive_where::derive_where; +use revm::{ + bytecode::opcode::OpCode, + context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv, Cfg, JournaledState}, + context_interface::{ + block::BlockSetter, + journaled_state::{AccountLoad, Eip7702CodeLoad}, + result::EVMError, + transaction::TransactionSetter, + Block, BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, Journal, JournalStateGetter, + JournalStateGetterDBError, Transaction, TransactionGetter, + }, + database_interface::{Database, EmptyDB}, + handler::{ + EthExecution, EthFrame, EthHandler, EthPostExecution, EthPreExecution, + EthPrecompileProvider, EthValidation, FrameResult, + }, + handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}, + interpreter::{ + instructions::host::{log, selfdestruct}, + interpreter::{EthInterpreter, InstructionProvider}, + interpreter_types::{Jumps, LoopControl}, + table::{self, CustomInstruction}, + CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, FrameInput, Host, + Instruction, InstructionResult, Interpreter, InterpreterTypes, SStoreResult, + SelfDestructResult, StateLoad, + }, + precompile::PrecompileErrors, + primitives::{Address, Bytes, Log, B256, U256}, + specification::hardfork::SpecId, + Context, Error, Evm, JournalEntry, +}; +use std::{rc::Rc, vec::Vec}; + + +pub trait JournalExt { + fn logs(&self) -> &[Log]; + + fn last_journal(&self) -> &[JournalEntry]; +} + +impl JournalExt for JournaledState { + fn logs(&self) -> &[Log] { + &self.logs + } + + fn last_journal(&self) -> &[JournalEntry] { + self.journal.last().expect("Journal is never empty") + } +} + +#[auto_impl(&, &mut, Box, Arc)] +pub trait JournalExtGetter { + type JournalExt: JournalExt; + + fn journal_ext(&self) -> &Self::JournalExt; +} \ No newline at end of file diff --git a/crates/inspector/src/lib.rs b/crates/inspector/src/lib.rs index 66e6f7084a..ed1b079605 100644 --- a/crates/inspector/src/lib.rs +++ b/crates/inspector/src/lib.rs @@ -9,6 +9,9 @@ extern crate alloc as std; mod eip3155; mod gas; mod inspector; +pub mod inspector_context; +pub mod inspector_frame; +mod journal; mod noop; pub use inspector::*; diff --git a/crates/optimism/src/evm.rs b/crates/optimism/src/evm.rs index 01d0148447..8ec02c2b1a 100644 --- a/crates/optimism/src/evm.rs +++ b/crates/optimism/src/evm.rs @@ -4,7 +4,7 @@ use crate::{ }, L1BlockInfo, OpSpec, OpTransaction, }; -use inspector::{InspectorContext, InspectorEthFrame}; +use inspector::{inspector_context::InspectorContext, inspector_frame::InspectorEthFrame}; use revm::{ context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context}, context_interface::result::{EVMError, InvalidTransaction}, diff --git a/examples/block_traces/src/main.rs b/examples/block_traces/src/main.rs index 1be8697258..4f621d2026 100644 --- a/examples/block_traces/src/main.rs +++ b/examples/block_traces/src/main.rs @@ -9,7 +9,10 @@ use alloy_provider::{ }; use database::{AlloyDB, CacheDB, StateBuilder}; use indicatif::ProgressBar; -use inspector::{inspectors::TracerEip3155, InspectorContext, InspectorEthFrame, InspectorMainEvm}; +use inspector::{ + inspector_context::InspectorContext, inspector_frame::InspectorEthFrame, + inspectors::TracerEip3155, InspectorMainEvm, +}; use revm::{ database_interface::WrapDatabaseAsync, handler::{