Skip to content

Commit

Permalink
refactor: decouple EVMData from Inspector trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Wodann committed Sep 25, 2023
1 parent afbc896 commit f14e47a
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 75 deletions.
27 changes: 23 additions & 4 deletions crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -61,7 +62,7 @@ impl<DB: Database + DatabaseCommit> EVM<DB> {
Ok(result)
}
/// Inspect transaction and commit changes to database.
pub fn inspect_commit<INSP: Inspector<DB>>(
pub fn inspect_commit<INSP: Inspector<DB::Error>>(
&mut self,
inspector: INSP,
) -> Result<ExecutionResult, EVMError<DB::Error>> {
Expand All @@ -84,7 +85,10 @@ impl<DB: Database> EVM<DB> {
}

/// Execute transaction with given inspector, without wring to DB. Return change state.
pub fn inspect<INSP: Inspector<DB>>(&mut self, mut inspector: INSP) -> EVMResult<DB::Error> {
pub fn inspect<INSP: Inspector<DB::Error>>(
&mut self,
mut inspector: INSP,
) -> EVMResult<DB::Error> {
if let Some(db) = self.db.as_mut() {
evm_inner::<DB, true>(&mut self.env, db, &mut inspector).transact()
} else {
Expand All @@ -110,7 +114,7 @@ impl<'a, DB: DatabaseRef> EVM<DB> {
}

/// Execute transaction with given inspector, without wring to DB. Return change state.
pub fn inspect_ref<INSP: Inspector<RefDBWrapper<'a, DB::Error>>>(
pub fn inspect_ref<INSP: Inspector<DB::Error>>(
&'a self,
mut inspector: INSP,
) -> EVMResult<DB::Error> {
Expand Down Expand Up @@ -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<DB>,
insp: &'a mut dyn Inspector<DB::Error>,
) -> Box<dyn Transact<DB::Error> + 'a> {
use specification::*;
match env.cfg.spec_id {
Expand All @@ -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<E> {
/// 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<Error = E>;

/// Returns a mutable reference to the last error, if one occured.
fn error(&mut self) -> &mut Option<E>;
}
39 changes: 29 additions & 10 deletions crates/revm/src/evm_impl.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<DB::Error>,
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<DB::Error>,
pub(crate) precompiles: Precompiles,
}

impl<'a, DB: Database> EVMData<DB::Error> 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<Error = DB::Error> {
self.db
}

fn error(&mut self) -> &mut Option<DB::Error> {
&mut self.error
}
}

pub struct EVMImpl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> {
data: EVMData<'a, DB>,
inspector: &'a mut dyn Inspector<DB>,
data: EVMDataImpl<'a, DB>,
inspector: &'a mut dyn Inspector<DB::Error>,
_phantomdata: PhantomData<GSPEC>,
}

Expand Down Expand Up @@ -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<DB>,
inspector: &'a mut dyn Inspector<DB::Error>,
precompiles: Precompiles,
) -> Self {
let journaled_state = if GSPEC::enabled(SpecId::SPURIOUS_DRAGON) {
Expand All @@ -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,
Expand Down
26 changes: 11 additions & 15 deletions crates/revm/src/inspector.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -26,15 +26,15 @@ pub mod inspectors {
}

#[auto_impl(&mut, Box)]
pub trait Inspector<DB: Database> {
pub trait Inspector<E> {
/// Called Before the interpreter is initialized.
///
/// If anything other than [InstructionResult::Continue] is returned then execution of the interpreter is
/// skipped.
fn initialize_interp(
&mut self,
_interp: &mut Interpreter,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
) -> InstructionResult {
InstructionResult::Continue
}
Expand All @@ -47,18 +47,14 @@ pub trait Inspector<DB: Database> {
/// # 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<E>) -> InstructionResult {
InstructionResult::Continue
}

/// Called when a log is emitted.
fn log(
&mut self,
_evm_data: &mut EVMData<'_, DB>,
_evm_data: &mut dyn EVMData<E>,
_address: &B160,
_topics: &[B256],
_data: &Bytes,
Expand All @@ -71,7 +67,7 @@ pub trait Inspector<DB: Database> {
fn step_end(
&mut self,
_interp: &mut Interpreter,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
_eval: InstructionResult,
) -> InstructionResult {
InstructionResult::Continue
Expand All @@ -82,7 +78,7 @@ pub trait Inspector<DB: Database> {
/// InstructionResulting anything other than [InstructionResult::Continue] overrides the result of the call.
fn call(
&mut self,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
_inputs: &mut CallInputs,
) -> (InstructionResult, Gas, Bytes) {
(InstructionResult::Continue, Gas::new(0), Bytes::new())
Expand All @@ -94,7 +90,7 @@ pub trait Inspector<DB: Database> {
/// out)`) will alter the result of the call.
fn call_end(
&mut self,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
_inputs: &CallInputs,
remaining_gas: Gas,
ret: InstructionResult,
Expand All @@ -108,7 +104,7 @@ pub trait Inspector<DB: Database> {
/// InstructionResulting anything other than [InstructionResult::Continue] overrides the result of the creation.
fn create(
&mut self,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
_inputs: &mut CreateInputs,
) -> (InstructionResult, Option<B160>, Gas, Bytes) {
(
Expand All @@ -125,7 +121,7 @@ pub trait Inspector<DB: Database> {
/// address, out)`) will alter the result of the create.
fn create_end(
&mut self,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
_inputs: &CreateInputs,
ret: InstructionResult,
address: Option<B160>,
Expand Down
21 changes: 11 additions & 10 deletions crates/revm/src/inspector/customprinter.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
//! 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<DB: Database> Inspector<DB> for CustomPrintTracer {
impl<E> Inspector<E> for CustomPrintTracer {
fn initialize_interp(
&mut self,
interp: &mut Interpreter,
data: &mut EVMData<'_, DB>,
data: &mut dyn EVMData<E>,
) -> InstructionResult {
self.gas_inspector.initialize_interp(interp, data);
InstructionResult::Continue
}

// 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<E>) -> InstructionResult {
let opcode = interp.current_opcode();
let opcode_str = opcode::OPCODE_JUMPMAP[opcode as usize];

let gas_remaining = self.gas_inspector.gas_remaining();

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,
Expand All @@ -49,7 +50,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
fn step_end(
&mut self,
interp: &mut Interpreter,
data: &mut EVMData<'_, DB>,
data: &mut dyn EVMData<E>,
eval: InstructionResult,
) -> InstructionResult {
self.gas_inspector.step_end(interp, data, eval);
Expand All @@ -58,7 +59,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {

fn call_end(
&mut self,
data: &mut EVMData<'_, DB>,
data: &mut dyn EVMData<E>,
inputs: &CallInputs,
remaining_gas: Gas,
ret: InstructionResult,
Expand All @@ -71,7 +72,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {

fn create_end(
&mut self,
data: &mut EVMData<'_, DB>,
data: &mut dyn EVMData<E>,
inputs: &CreateInputs,
ret: InstructionResult,
address: Option<B160>,
Expand All @@ -85,7 +86,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {

fn call(
&mut self,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
inputs: &mut CallInputs,
) -> (InstructionResult, Gas, Bytes) {
println!(
Expand All @@ -101,7 +102,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {

fn create(
&mut self,
_data: &mut EVMData<'_, DB>,
_data: &mut dyn EVMData<E>,
inputs: &mut CreateInputs,
) -> (InstructionResult, Option<B160>, Gas, Bytes) {
println!(
Expand Down
Loading

0 comments on commit f14e47a

Please sign in to comment.