From 0fbc69ba15da3abe4bd0dcc57116b3bf091aa08b Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 16 Nov 2023 02:50:38 +0100 Subject: [PATCH] Init tracer and generalize gaosmeter over standard invoker --- Cargo.toml | 1 + interpreter/src/call_create.rs | 14 +++ jsontests/src/run.rs | 4 +- src/gasometer.rs | 6 +- src/standard/gasometer/mod.rs | 78 +++++++++++++- src/standard/invoker/mod.rs | 172 ++++++++++++++++--------------- src/standard/invoker/routines.rs | 76 +++++++------- src/standard/mod.rs | 4 +- tracer/Cargo.toml | 7 ++ tracer/src/lib.rs | 7 ++ tracer/src/standard.rs | 12 +++ 11 files changed, 247 insertions(+), 134 deletions(-) create mode 100644 tracer/Cargo.toml create mode 100644 tracer/src/lib.rs create mode 100644 tracer/src/standard.rs diff --git a/Cargo.toml b/Cargo.toml index 3a69966b9..4cf25a5d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,4 +61,5 @@ with-serde = [ members = [ "interpreter", "jsontests", + "tracer", ] diff --git a/interpreter/src/call_create.rs b/interpreter/src/call_create.rs index b053c46e4..7fc853ae0 100644 --- a/interpreter/src/call_create.rs +++ b/interpreter/src/call_create.rs @@ -111,6 +111,13 @@ impl CallCreateTrapData { _ => Err(ExitException::InvalidOpcode(opcode).into()), } } + + pub fn code(&self, handler: &H) -> Vec { + match self { + Self::Call(trap) => handler.code(trap.target), + Self::Create(trap) => trap.code.clone(), + } + } } pub struct CallTrapData { @@ -311,6 +318,13 @@ impl CallTrapData { Err(e) => Err(e), } } + + pub fn has_value(&self) -> bool { + self.transfer + .as_ref() + .map(|t| t.value != U256::zero()) + .unwrap_or(false) + } } #[derive(Clone, Debug)] diff --git a/jsontests/src/run.rs b/jsontests/src/run.rs index 7d4044b72..4a84f47dd 100644 --- a/jsontests/src/run.rs +++ b/jsontests/src/run.rs @@ -3,7 +3,7 @@ use crate::types::*; use evm::backend::in_memory::{ InMemoryAccount, InMemoryBackend, InMemoryEnvironment, InMemoryLayer, }; -use evm::standard::{Config, Etable, Invoker}; +use evm::standard::{Config, Etable, Gasometer, Invoker}; use evm::utils::u256_to_h256; use primitive_types::U256; use std::collections::{BTreeMap, BTreeSet}; @@ -62,7 +62,7 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test) -> Result<(), Err let etable = Etable::runtime(); let invoker = Invoker::new(&config); - let _result = invoker.transact_call( + let _result = invoker.transact_call::( test.transaction.sender, test.transaction.to, test.transaction.value, diff --git a/src/gasometer.rs b/src/gasometer.rs index 404936c2b..97a065b00 100644 --- a/src/gasometer.rs +++ b/src/gasometer.rs @@ -21,11 +21,10 @@ impl Gas for U256 {} pub enum GasometerMergeStrategy { Commit, Revert, + Discard, } pub trait Gasometer: Sized { - type Gas: Gas; - fn record_stepn( &mut self, machine: &Machine, @@ -33,7 +32,8 @@ pub trait Gasometer: Sized { backend: &H, ) -> Result; fn record_codedeposit(&mut self, len: usize) -> Result<(), ExitError>; - fn gas(&self) -> Self::Gas; + fn gas(&self) -> U256; + fn submeter(&mut self, gas_limit: U256, code: &[u8]) -> Result; fn merge(&mut self, other: Self, strategy: GasometerMergeStrategy); } diff --git a/src/standard/gasometer/mod.rs b/src/standard/gasometer/mod.rs index 200727324..f3373ab04 100644 --- a/src/standard/gasometer/mod.rs +++ b/src/standard/gasometer/mod.rs @@ -10,6 +10,23 @@ use crate::{ use core::cmp::max; use primitive_types::{H160, H256, U256}; +pub trait TransactGasometer<'config, S: AsRef>: Sized { + fn new_transact_call( + gas_limit: U256, + code: &[u8], + data: &[u8], + access_list: &Vec<(H160, Vec)>, + config: &'config Config, + ) -> Result; + + fn new_transact_create( + gas_limit: U256, + code: &[u8], + access_list: &Vec<(H160, Vec)>, + config: &'config Config, + ) -> Result; +} + pub struct Gasometer<'config> { gas_limit: u64, memory_gas: u64, @@ -58,7 +75,7 @@ impl<'config> Gasometer<'config> { } } - pub fn new(gas_limit: u64, _machine: &Machine, config: &'config Config) -> Self { + pub fn new(gas_limit: u64, _code: &[u8], config: &'config Config) -> Self { Self { gas_limit, memory_gas: 0, @@ -69,9 +86,48 @@ impl<'config> Gasometer<'config> { } } -impl<'config, S: AsRef, H: RuntimeBackend> GasometerT for Gasometer<'config> { - type Gas = u64; +impl<'config, S: AsRef> TransactGasometer<'config, S> for Gasometer<'config> { + fn new_transact_call( + gas_limit: U256, + code: &[u8], + data: &[u8], + access_list: &Vec<(H160, Vec)>, + config: &'config Config, + ) -> Result { + let gas_limit = if gas_limit > U256::from(u64::MAX) { + return Err(ExitException::OutOfGas.into()); + } else { + gas_limit.as_u64() + }; + + let mut s = Self::new(gas_limit, code, config); + let transaction_cost = TransactionCost::call(data, access_list).cost(config); + + s.record_cost(transaction_cost)?; + Ok(s) + } + + fn new_transact_create( + gas_limit: U256, + code: &[u8], + access_list: &Vec<(H160, Vec)>, + config: &'config Config, + ) -> Result { + let gas_limit = if gas_limit > U256::from(u64::MAX) { + return Err(ExitException::OutOfGas.into()); + } else { + gas_limit.as_u64() + }; + + let mut s = Self::new(gas_limit, code, config); + let transaction_cost = TransactionCost::create(code, access_list).cost(config); + + s.record_cost(transaction_cost)?; + Ok(s) + } +} +impl<'config, S: AsRef, H: RuntimeBackend> GasometerT for Gasometer<'config> { fn record_stepn( &mut self, machine: &Machine, @@ -125,8 +181,19 @@ impl<'config, S: AsRef, H: RuntimeBackend> GasometerT for Ga }) } - fn gas(&self) -> u64 { - self.gas() + fn gas(&self) -> U256 { + self.gas().into() + } + + fn submeter(&mut self, gas_limit: U256, code: &[u8]) -> Result { + let gas_limit = if gas_limit > U256::from(u64::MAX) { + return Err(ExitException::OutOfGas.into()); + } else { + gas_limit.as_u64() + }; + + self.record_cost(gas_limit)?; + Ok(Self::new(gas_limit, code, self.config)) } fn merge(&mut self, other: Self, strategy: GasometerMergeStrategy) { @@ -138,6 +205,7 @@ impl<'config, S: AsRef, H: RuntimeBackend> GasometerT for Ga GasometerMergeStrategy::Revert => { self.used_gas -= other.gas(); } + GasometerMergeStrategy::Discard => {} } } } diff --git a/src/standard/invoker/mod.rs b/src/standard/invoker/mod.rs index 92cf0a011..5b90636c2 100644 --- a/src/standard/invoker/mod.rs +++ b/src/standard/invoker/mod.rs @@ -1,7 +1,7 @@ mod routines; use self::routines::try_or_oog; -use super::{gasometer::TransactionCost, Config, Etable, GasedMachine, Gasometer}; +use super::{Config, Etable, GasedMachine, TransactGasometer}; use crate::call_create::{CallCreateTrapData, CallTrapData, CreateScheme, CreateTrapData}; use crate::{ Capture, Context, ExitError, ExitException, ExitResult, Gasometer as GasometerT, @@ -14,15 +14,17 @@ use core::convert::Infallible; use primitive_types::{H160, H256, U256}; use sha3::{Digest, Keccak256}; -pub enum CallCreateTrapPrepareData { +pub enum CallCreateTrapPrepareData { Call { - gas_limit: u64, + gasometer: G, + code: Vec, is_static: bool, transaction_context: Rc, trap: CallTrapData, }, Create { - gas_limit: u64, + gasometer: G, + code: Vec, is_static: bool, transaction_context: Rc, trap: CreateTrapData, @@ -45,7 +47,7 @@ impl<'config> Invoker<'config> { Self { config } } - pub fn transact_call( + pub fn transact_call( &self, caller: H160, address: H160, @@ -58,6 +60,7 @@ impl<'config> Invoker<'config> { etable: &Etable, ) -> ExitResult where + G: GasometerT + TransactGasometer<'config, RuntimeState>, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { routines::transact_and_work( @@ -67,12 +70,6 @@ impl<'config> Invoker<'config> { gas_price, handler, |handler: &mut H| -> (ExitResult, U256) { - let gas_limit = if gas_limit > U256::from(u64::MAX) { - return (Err(ExitException::OutOfGas.into()), U256::zero()); - } else { - gas_limit.as_u64() - }; - let context = Context { caller, address, @@ -88,26 +85,28 @@ impl<'config> Invoker<'config> { gas_price, }; - let transaction_cost = TransactionCost::call(&data, &access_list).cost(self.config); - if gas_limit < transaction_cost { - return (Err(ExitException::OutOfGas.into()), U256::zero()); - } + let code = handler.code(address); + + let gasometer = try_or_oog!(G::new_transact_call( + gas_limit, + &code, + &data, + &access_list, + self.config + )); - let mut machine = try_or_oog!(routines::make_enter_call_machine( + let machine = try_or_oog!(routines::make_enter_call_machine( self, - true, // is_transaction - address, + code, data, - gas_limit, false, // is_static Some(transfer), context, Rc::new(transaction_context), + gasometer, handler )); - try_or_oog!(machine.gasometer.record_cost(transaction_cost)); - if self.config.increase_state_access_gas { if self.config.warm_coinbase_address { let coinbase = handler.block_coinbase(); @@ -128,7 +127,7 @@ impl<'config> Invoker<'config> { ) } - pub fn transact_create( + pub fn transact_create( &self, caller: H160, value: U256, @@ -140,6 +139,7 @@ impl<'config> Invoker<'config> { etable: &Etable, ) -> Result where + G: GasometerT + TransactGasometer<'config, RuntimeState>, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { routines::transact_and_work( @@ -149,12 +149,6 @@ impl<'config> Invoker<'config> { gas_price, handler, |handler| -> (Result, U256) { - let gas_limit = if gas_limit > U256::from(u64::MAX) { - return (Err(ExitException::OutOfGas.into()), U256::zero()); - } else { - gas_limit.as_u64() - }; - let scheme = CreateScheme::Legacy { caller }; let address = scheme.address(handler); @@ -172,25 +166,25 @@ impl<'config> Invoker<'config> { target: address, value, }; - let transaction_cost = - TransactionCost::create(&init_code, &access_list).cost(self.config); - if gas_limit < transaction_cost { - return (Err(ExitException::OutOfGas.into()), U256::zero()); - } - let mut machine = try_or_oog!(routines::make_enter_create_machine( + let gasometer = try_or_oog!(G::new_transact_create( + gas_limit, + &init_code, + &access_list, + self.config + )); + + let machine = try_or_oog!(routines::make_enter_create_machine( self, caller, - address, init_code, - gas_limit, - false, + false, // is_static transfer, context, Rc::new(transaction_context), + gasometer, handler, )); - try_or_oog!(machine.gasometer.record_cost(transaction_cost)); let (mut machine, result) = crate::execute(machine, handler, 0, DEFAULT_HEAP_DEPTH, self, etable); @@ -209,7 +203,7 @@ impl<'config> Invoker<'config> { ) } - pub fn transact_create2( + pub fn transact_create2( &self, caller: H160, value: U256, @@ -222,6 +216,7 @@ impl<'config> Invoker<'config> { etable: &Etable, ) -> Result where + G: GasometerT + TransactGasometer<'config, RuntimeState>, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { routines::transact_and_work( @@ -231,12 +226,6 @@ impl<'config> Invoker<'config> { gas_price, handler, |handler| -> (Result, U256) { - let gas_limit = if gas_limit > U256::from(u64::MAX) { - return (Err(ExitException::OutOfGas.into()), U256::zero()); - } else { - gas_limit.as_u64() - }; - let scheme = CreateScheme::Create2 { caller, code_hash: H256::from_slice(Keccak256::digest(&init_code).as_slice()), @@ -258,25 +247,25 @@ impl<'config> Invoker<'config> { target: address, value, }; - let transaction_cost = - TransactionCost::create(&init_code, &access_list).cost(self.config); - if gas_limit < transaction_cost { - return (Err(ExitException::OutOfGas.into()), U256::zero()); - } - let mut machine = try_or_oog!(routines::make_enter_create_machine( + let gasometer = try_or_oog!(G::new_transact_create( + gas_limit, + &init_code, + &access_list, + self.config + )); + + let machine = try_or_oog!(routines::make_enter_create_machine( self, caller, - address, init_code, - gas_limit, - false, + false, // is_static transfer, context, Rc::new(transaction_context), + gasometer, handler, )); - try_or_oog!(machine.gasometer.record_cost(transaction_cost)); let (mut machine, result) = crate::execute(machine, handler, 0, DEFAULT_HEAP_DEPTH, self, etable); @@ -296,23 +285,24 @@ impl<'config> Invoker<'config> { } } -impl<'config, H> InvokerT, H, Opcode> for Invoker<'config> +impl<'config, G, H> InvokerT for Invoker<'config> where + G: GasometerT, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { type Interrupt = Infallible; - type CallCreateTrapPrepareData = CallCreateTrapPrepareData; + type CallCreateTrapPrepareData = CallCreateTrapPrepareData; type CallCreateTrapEnterData = CallCreateTrapEnterData; fn prepare_trap( &self, opcode: Opcode, - machine: &mut GasedMachine<'config>, - _handler: &mut H, + machine: &mut GasedMachine, + handler: &mut H, depth: usize, ) -> Capture, Infallible> { - fn l64(gas: u64) -> u64 { - gas - gas / 64 + fn l64(gas: U256) -> U256 { + gas - gas / U256::from(64) } if depth >= self.config.call_stack_limit { @@ -324,23 +314,19 @@ where Err(err) => return Capture::Exit(Err(err)), }; - let after_gas = U256::from(if self.config.call_l64_after_gas { + let after_gas = if self.config.call_l64_after_gas { l64(machine.gasometer.gas()) } else { machine.gasometer.gas() - }); - let target_gas = trap_data.target_gas().unwrap_or(after_gas); - let gas_limit = min(after_gas, target_gas); - - let gas_limit = if gas_limit > U256::from(u64::MAX) { - return Capture::Exit(Err(ExitException::OutOfGas.into())); - } else { - gas_limit.as_u64() }; + let target_gas = trap_data.target_gas().unwrap_or(after_gas); + let mut gas_limit = min(after_gas, target_gas); - match machine.gasometer.record_cost(gas_limit) { - Ok(()) => (), - Err(err) => return Capture::Exit(Err(err)), + match &trap_data { + CallCreateTrapData::Call(call) if call.has_value() => { + gas_limit = gas_limit.saturating_add(U256::from(self.config.call_stipend)); + } + _ => (), } let is_static = if machine.is_static { @@ -354,15 +340,23 @@ where let transaction_context = machine.machine.state.as_ref().transaction_context.clone(); + let code = trap_data.code(handler); + let submeter = match machine.gasometer.submeter(gas_limit, &code) { + Ok(submeter) => submeter, + Err(err) => return Capture::Exit(Err(err)), + }; + Capture::Exit(Ok(match trap_data { CallCreateTrapData::Call(call_trap_data) => CallCreateTrapPrepareData::Call { - gas_limit, + gasometer: submeter, + code, is_static, transaction_context, trap: call_trap_data, }, CallCreateTrapData::Create(create_trap_data) => CallCreateTrapPrepareData::Create { - gas_limit, + gasometer: submeter, + code, is_static, transaction_context, trap: create_trap_data, @@ -374,32 +368,36 @@ where &self, trap_data: Self::CallCreateTrapPrepareData, handler: &mut H, - ) -> Result<(Self::CallCreateTrapEnterData, GasedMachine<'config>), ExitError> { + ) -> Result<(Self::CallCreateTrapEnterData, GasedMachine), ExitError> { match trap_data { CallCreateTrapPrepareData::Create { - gas_limit, + gasometer, + code, is_static, transaction_context, trap, } => routines::enter_create_trap_stack( self, + code, trap, - gas_limit, is_static, transaction_context, + gasometer, handler, ), CallCreateTrapPrepareData::Call { - gas_limit, + gasometer, + code, is_static, transaction_context, trap, } => routines::enter_call_trap_stack( self, + code, trap, - gas_limit, is_static, transaction_context, + gasometer, handler, ), } @@ -408,9 +406,9 @@ where fn exit_trap_stack( &self, result: ExitResult, - mut child: GasedMachine<'config>, + mut child: GasedMachine, trap_data: Self::CallCreateTrapEnterData, - parent: &mut GasedMachine<'config>, + parent: &mut GasedMachine, handler: &mut H, ) -> Result<(), ExitError> { match trap_data { @@ -443,6 +441,11 @@ where } Err(_) => { handler.pop_substate(TransactionalMergeStrategy::Discard); + GasometerT::::merge( + &mut parent.gasometer, + child.gasometer, + GasometerMergeStrategy::Discard, + ); } }; @@ -472,6 +475,11 @@ where } Err(_) => { handler.pop_substate(TransactionalMergeStrategy::Discard); + GasometerT::::merge( + &mut parent.gasometer, + child.gasometer, + GasometerMergeStrategy::Discard, + ); } }; diff --git a/src/standard/invoker/routines.rs b/src/standard/invoker/routines.rs index 1d7ae9233..6e84973f1 100644 --- a/src/standard/invoker/routines.rs +++ b/src/standard/invoker/routines.rs @@ -1,5 +1,5 @@ use super::{CallCreateTrapEnterData, CallTrapData, CreateTrapData, Invoker}; -use crate::standard::{Config, GasedMachine, Gasometer, Machine}; +use crate::standard::{Config, GasedMachine, Machine}; use crate::{ Context, ExitError, ExitException, Gasometer as GasometerT, Opcode, RuntimeBackend, RuntimeEnvironment, RuntimeState, TransactionContext, TransactionalBackend, @@ -54,29 +54,24 @@ where } } -pub fn make_enter_call_machine<'config, H>( +pub fn make_enter_call_machine<'config, G, H>( invoker: &Invoker<'config>, - is_transaction: bool, - target: H160, + code: Vec, input: Vec, - mut gas_limit: u64, is_static: bool, transfer: Option, context: Context, transaction_context: Rc, + gasometer: G, handler: &mut H, -) -> Result, ExitError> +) -> Result, ExitError> where + G: GasometerT, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { handler.mark_hot(context.address, None)?; - let code = handler.code(target); - - if let Some(transfer) = transfer.clone() { - if !is_transaction && transfer.value != U256::zero() { - gas_limit = gas_limit.saturating_add(invoker.config.call_stipend); - } + if let Some(transfer) = transfer { handler.transfer(transfer)?; } @@ -95,8 +90,6 @@ where }, ); - let gasometer = Gasometer::new(gas_limit, &machine, invoker.config); - Ok(GasedMachine { machine, gasometer, @@ -104,19 +97,19 @@ where }) } -pub fn make_enter_create_machine<'config, H>( +pub fn make_enter_create_machine<'config, G, H>( invoker: &Invoker<'config>, caller: H160, - target: H160, init_code: Vec, - gas_limit: u64, is_static: bool, transfer: Transfer, context: Context, transaction_context: Rc, + gasometer: G, handler: &mut H, -) -> Result, ExitError> +) -> Result, ExitError> where + G: GasometerT, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { if let Some(limit) = invoker.config.max_initcode_size { @@ -126,19 +119,21 @@ where } handler.mark_hot(caller, None)?; - handler.mark_hot(target, None)?; + handler.mark_hot(context.address, None)?; handler.transfer(transfer)?; - if handler.code_size(target) != U256::zero() || handler.nonce(target) > U256::zero() { + if handler.code_size(context.address) != U256::zero() + || handler.nonce(context.address) > U256::zero() + { return Err(ExitException::CreateCollision.into()); } handler.inc_nonce(caller)?; if invoker.config.create_increase_nonce { - handler.inc_nonce(target)?; + handler.inc_nonce(context.address)?; } - handler.reset_storage(target); + handler.reset_storage(context.address); let machine = Machine::new( Rc::new(init_code), @@ -153,8 +148,6 @@ where }, ); - let gasometer = Gasometer::new(gas_limit, &machine, invoker.config); - Ok(GasedMachine { machine, gasometer, @@ -162,30 +155,31 @@ where }) } -pub fn enter_call_trap_stack<'config, H>( +pub fn enter_call_trap_stack<'config, G, H>( invoker: &Invoker<'config>, + code: Vec, trap_data: CallTrapData, - gas_limit: u64, is_static: bool, transaction_context: Rc, + gasometer: G, handler: &mut H, -) -> Result<(CallCreateTrapEnterData, GasedMachine<'config>), ExitError> +) -> Result<(CallCreateTrapEnterData, GasedMachine), ExitError> where + G: GasometerT, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { handler.push_substate(); - let work = || -> Result<(CallCreateTrapEnterData, GasedMachine<'config>), ExitError> { + let work = || -> Result<(CallCreateTrapEnterData, GasedMachine), ExitError> { let machine = make_enter_call_machine( invoker, - false, // is_transaction - trap_data.target, + code, trap_data.input.clone(), - gas_limit, is_static, trap_data.transfer.clone(), trap_data.context.clone(), transaction_context, + gasometer, handler, )?; @@ -201,24 +195,26 @@ where } } -pub fn enter_create_trap_stack<'config, H>( +pub fn enter_create_trap_stack<'config, G, H>( invoker: &Invoker<'config>, + code: Vec, trap_data: CreateTrapData, - gas_limit: u64, is_static: bool, transaction_context: Rc, + gasometer: G, handler: &mut H, -) -> Result<(CallCreateTrapEnterData, GasedMachine<'config>), ExitError> +) -> Result<(CallCreateTrapEnterData, GasedMachine), ExitError> where + G: GasometerT, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { handler.push_substate(); - let work = || -> Result<(CallCreateTrapEnterData, GasedMachine<'config>), ExitError> { + let work = || -> Result<(CallCreateTrapEnterData, GasedMachine), ExitError> { let CreateTrapData { scheme, value, - code, + code: _, } = trap_data.clone(); let caller = scheme.caller(); @@ -239,13 +235,12 @@ where let machine = make_enter_create_machine( invoker, caller, - address, code, - gas_limit, is_static, transfer, context, transaction_context, + gasometer, handler, )?; @@ -274,14 +269,15 @@ fn check_first_byte(config: &Config, code: &[u8]) -> Result<(), ExitError> { Ok(()) } -pub fn deploy_create_code<'config, H>( +pub fn deploy_create_code<'config, G, H>( invoker: &Invoker<'config>, result: Result, retbuf: &Vec, - gasometer: &mut Gasometer<'config>, + gasometer: &mut G, handler: &mut H, ) -> Result where + G: GasometerT, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, { let address = result?; diff --git a/src/standard/mod.rs b/src/standard/mod.rs index 18afd3a3d..f6ab311be 100644 --- a/src/standard/mod.rs +++ b/src/standard/mod.rs @@ -3,10 +3,10 @@ mod gasometer; mod invoker; pub use self::config::Config; -pub use self::gasometer::Gasometer; +pub use self::gasometer::{Gasometer, TransactGasometer}; pub use self::invoker::Invoker; pub type Machine = crate::Machine; pub type Efn = crate::Efn; pub type Etable> = crate::Etable; -pub type GasedMachine<'config> = crate::GasedMachine>; +pub type GasedMachine = crate::GasedMachine; diff --git a/tracer/Cargo.toml b/tracer/Cargo.toml new file mode 100644 index 000000000..7550e4350 --- /dev/null +++ b/tracer/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "evm-tracer" +version = "0.1.0" +edition = "2021" + +[dependencies] +evm = { path = ".." } diff --git a/tracer/src/lib.rs b/tracer/src/lib.rs new file mode 100644 index 000000000..7b0b01f81 --- /dev/null +++ b/tracer/src/lib.rs @@ -0,0 +1,7 @@ +mod standard; + +use evm::{Machine, Opcode}; + +pub trait EvalTracer { + fn on_eval(&mut self, machine: &Machine, handle: &H, opcode: Opcode, position: usize); +} diff --git a/tracer/src/standard.rs b/tracer/src/standard.rs new file mode 100644 index 000000000..ff9687ebc --- /dev/null +++ b/tracer/src/standard.rs @@ -0,0 +1,12 @@ +use evm::standard::Machine; +use evm::{Opcode, RuntimeState}; + +pub trait EvalTracer { + fn on_eval(&mut self, machine: &Machine, handle: &H, opcode: Opcode, position: usize); +} + +impl> crate::EvalTracer for T { + fn on_eval(&mut self, machine: &Machine, handle: &H, opcode: Opcode, position: usize) { + EvalTracer::::on_eval(self, machine, handle, opcode, position) + } +}