diff --git a/Cargo.lock b/Cargo.lock index 1fc05a774c..d1a0a6653d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1206,12 +1206,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - [[package]] name = "ecdsa" version = "0.16.9" @@ -2852,7 +2846,6 @@ dependencies = [ "revm-specification", "revm-state", "rstest", - "serde", ] [[package]] @@ -2871,15 +2864,12 @@ dependencies = [ name = "revm-context" version = "1.0.0" dependencies = [ - "auto_impl", "derive-where", - "dyn-clone", "revm-bytecode", "revm-context-interface", "revm-database", "revm-database-interface", "revm-interpreter", - "revm-precompile", "revm-primitives", "revm-specification", "revm-state", @@ -2892,8 +2882,6 @@ version = "1.0.0" dependencies = [ "auto_impl", "cfg-if", - "dyn-clone", - "revm-bytecode", "revm-database", "revm-database-interface", "revm-primitives", @@ -2945,9 +2933,6 @@ dependencies = [ name = "revm-handler" version = "1.0.0" dependencies = [ - "auto_impl", - "derive-where", - "dyn-clone", "revm-bytecode", "revm-context-interface", "revm-database", @@ -2987,7 +2972,6 @@ name = "revm-interpreter" version = "10.0.1" dependencies = [ "bincode", - "derive-where", "revm-bytecode", "revm-context-interface", "revm-database-interface", @@ -3007,7 +2991,6 @@ dependencies = [ "c-kzg", "cfg-if", "criterion", - "dyn-clone", "eyre", "k256", "kzg-rs", diff --git a/Cargo.toml b/Cargo.toml index 204f6619aa..6c1e75edb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,10 @@ context-interface = { path = "crates/context/interface", package = "revm-context handler = { path = "crates/handler", package = "revm-handler", version = "1.0.0", default-features = false } handler-interface = { path = "crates/handler/interface", package = "revm-handler-interface", version = "1.0.0", default-features = false } +# mics +cfg-if = { version = "1.0", default-features = false } +auto_impl = { version = "1.2.0" } +derive-where = { version = "1.2.7", default-features = false } [workspace.package] license = "MIT" diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 91196297ac..c9c4fd8257 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -458,6 +458,7 @@ pub fn execute_test_suite( error: Ok(()), }, inspector: StepPrintInspector::new(), + frame_input_stack: Vec::new(), }, handler: EthHandler::new( EthValidation::new(), diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index 54c2a3321e..d96cf5ea49 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -138,6 +138,12 @@ impl OpCode { } } + /// Returns the opcode as a usize. + #[inline] + pub const fn as_usize(&self) -> usize { + self.0 as usize + } + /// Returns the opcode information. #[inline] pub const fn info(&self) -> OpCodeInfo { diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 90433cc19c..fcd3ecdf8f 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -24,7 +24,6 @@ all = "warn" [dependencies] # revm interpreter.workspace = true -precompile.workspace = true context-interface.workspace = true primitives.workspace = true database-interface.workspace = true @@ -34,9 +33,7 @@ bytecode.workspace = true database = { workspace = true, optional = true } # misc -derive-where = { version = "1.2.7", default-features = false } -dyn-clone = "1.0" -auto_impl = "1.2.0" +derive-where.workspace = true # Optional serde = { version = "1.0", default-features = false, features = [ diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index d1c9807e35..49d0a71bc0 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -27,12 +27,10 @@ primitives.workspace = true database-interface.workspace = true state.workspace = true specification.workspace = true -bytecode.workspace = true # mics -dyn-clone = "1.0" -cfg-if = { version = "1.0", default-features = false } -auto_impl = "1.2.0" +cfg-if.workspace = true +auto_impl.workspace = true # Optional serde = { version = "1.0", default-features = false, features = [ diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index 64fe335906..e3d3e51533 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -22,10 +22,12 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] +# revm state.workspace = true primitives.workspace = true -auto_impl = "1.2" +# mics +auto_impl.workspace = true # Optional serde = { version = "1.0", default-features = false, features = [ @@ -48,6 +50,4 @@ alloy-sol-types = "0.8" default = ["std"] std = ["serde?/std"] serde = ["dep:serde"] -asyncdb = [ - "dep:tokio", -] +asyncdb = ["dep:tokio"] diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index a19de9f25b..53cf7d605b 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -33,11 +33,6 @@ bytecode.workspace = true database = { workspace = true, optional = true } handler-interface.workspace = true -# misc -derive-where = { version = "1.2.7", default-features = false } -dyn-clone = "1.0" -auto_impl = "1.2.0" - # Optional serde = { version = "1.0", default-features = false, features = [ "derive", diff --git a/crates/handler/interface/src/frame.rs b/crates/handler/interface/src/frame.rs index 7c6ffb68ee..7b913f8429 100644 --- a/crates/handler/interface/src/frame.rs +++ b/crates/handler/interface/src/frame.rs @@ -8,14 +8,14 @@ pub trait Frame: Sized { type Error; fn init_first( - cxt: &mut Self::Context, - frame_action: Self::FrameInit, + ctx: &mut Self::Context, + frame_input: Self::FrameInit, ) -> Result, Self::Error>; fn init( &self, - cxt: &mut Self::Context, - frame_action: Self::FrameInit, + ctx: &mut Self::Context, + frame_input: Self::FrameInit, ) -> Result, Self::Error>; fn run( @@ -25,7 +25,7 @@ pub trait Frame: Sized { fn return_result( &mut self, - cxt: &mut Self::Context, + ctx: &mut Self::Context, result: Self::FrameResult, ) -> Result<(), Self::Error>; } diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index 0b7fd59411..43a747fbe0 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -8,7 +8,7 @@ use handler_interface::{ExecutionHandler, Frame as FrameTrait, FrameOrResultGen} use interpreter::{ interpreter::{EthInstructionProvider, EthInterpreter}, return_ok, return_revert, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, - EOFCreateInputs, EOFCreateKind, Gas, NewFrameAction, + EOFCreateInputs, EOFCreateKind, FrameInput, Gas, }; use primitives::TxKind; use specification::hardfork::SpecId; @@ -37,12 +37,8 @@ where + JournalStateGetter + CfgGetter, ERROR: From + From>, - FRAME: FrameTrait< - Context = CTX, - Error = ERROR, - FrameInit = NewFrameAction, - FrameResult = FrameResult, - >, + FRAME: + FrameTrait, { type Context = CTX; type Error = ERROR; @@ -60,8 +56,8 @@ where let tx = context.tx(); let input = tx.common_fields().input().clone(); - let init_frame: NewFrameAction = match tx.kind() { - TxKind::Call(target_address) => NewFrameAction::Call(Box::new(CallInputs { + let init_frame: FrameInput = match tx.kind() { + TxKind::Call(target_address) => FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address, @@ -76,14 +72,14 @@ where TxKind::Create => { // if first byte of data is magic 0xEF00, then it is EOFCreate. if spec.is_enabled_in(SpecId::PRAGUE_EOF) && input.starts_with(&EOF_MAGIC_BYTES) { - NewFrameAction::EOFCreate(Box::new(EOFCreateInputs::new( + FrameInput::EOFCreate(Box::new(EOFCreateInputs::new( tx.common_fields().caller(), tx.common_fields().value(), gas_limit, EOFCreateKind::Tx { initdata: input }, ))) } else { - NewFrameAction::Create(Box::new(CreateInputs { + FrameInput::Create(Box::new(CreateInputs { caller: tx.common_fields().caller(), scheme: CreateScheme::Create, value: tx.common_fields().value(), diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index d6d235b093..4992a1061c 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -12,8 +12,8 @@ use interpreter::{ interpreter::{EthInterpreter, InstructionProvider}, interpreter_wiring::{LoopControl, ReturnData, RuntimeFlag}, return_ok, return_revert, CallInputs, CallOutcome, CallValue, CreateInputs, CreateOutcome, - CreateScheme, EOFCreateInputs, EOFCreateKind, Gas, Host, InputsImpl, InstructionResult, - InterpreterAction, InterpreterResult, InterpreterWire, NewFrameAction, NewInterpreter, + CreateScheme, EOFCreateInputs, EOFCreateKind, FrameInput, Gas, Host, InputsImpl, + InstructionResult, InterpreterAction, InterpreterResult, InterpreterWire, NewInterpreter, SharedMemory, }; use precompile::PrecompileErrors; @@ -72,7 +72,7 @@ pub struct EthFrame { pub interpreter: NewInterpreter, /// Precompiles provider. pub precompiles: PRECOMPILE, - /// Insturction provider. + /// Instruction provider. pub instructions: INSTRUCTIONS, // This is worth making as a generic type FrameSharedContext. pub memory: Rc>, @@ -191,7 +191,8 @@ where } else { let account = ctx.journal().load_account_code(inputs.bytecode_address)?; - let code_hash = account.info.code_hash(); + // TODO Request from foundry to get bytecode hash. + let _code_hash = account.info.code_hash(); let mut bytecode = account.info.code.clone().unwrap_or_default(); // ExtDelegateCall is not allowed to call non-EOF contracts. @@ -301,12 +302,13 @@ where } // Create address - let mut init_code_hash = B256::ZERO; + // TODO incorporating code hash inside interpreter. It was a request by foundry. + 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) } }; @@ -452,12 +454,10 @@ where return return_error(InstructionResult::CreateCollision); }; - let bytecode = Bytecode::new_legacy(input).into_analyzed(); - let interpreter_input = InputsImpl { target_address: created_address, caller_address: inputs.caller, - input: Bytes::new(), + input, call_value: inputs.value, }; @@ -465,7 +465,7 @@ where FrameData::Create(CreateFrame { created_address }), NewInterpreter::new( memory.clone(), - bytecode, + Bytecode::Eof(Arc::new(initcode)), interpreter_input, false, false, @@ -481,20 +481,20 @@ where pub fn init_with_context( depth: usize, - frame_init: NewFrameAction, + frame_init: FrameInput, memory: Rc>, precompile: PRECOMPILE, instructions: INSTRUCTION, ctx: &mut CTX, ) -> Result, ERROR> { match frame_init { - NewFrameAction::Call(inputs) => { + FrameInput::Call(inputs) => { Self::make_call_frame(ctx, depth, memory, &inputs, precompile, instructions) } - NewFrameAction::Create(inputs) => { + FrameInput::Create(inputs) => { Self::make_create_frame(ctx, depth, memory, &inputs, precompile, instructions) } - NewFrameAction::EOFCreate(inputs) => { + FrameInput::EOFCreate(inputs) => { Self::make_eofcreate_frame(ctx, depth, memory, &inputs, precompile, instructions) } } @@ -516,12 +516,12 @@ where { type Context = CTX; type Error = ERROR; - type FrameInit = NewFrameAction; + type FrameInit = FrameInput; type FrameResult = FrameResult; fn init_first( ctx: &mut Self::Context, - frame_action: Self::FrameInit, + frame_input: Self::FrameInit, ) -> Result, Self::Error> { let memory = Rc::new(RefCell::new(SharedMemory::new())); let precompiles = PRECOMPILE::new(ctx); @@ -533,7 +533,7 @@ where } memory.borrow_mut().new_context(); - Self::init_with_context(0, frame_action, memory, precompiles, instructions, ctx) + Self::init_with_context(0, frame_input, memory, precompiles, instructions, ctx) } fn init( diff --git a/crates/handler/src/lib.rs b/crates/handler/src/lib.rs index a2925c33ce..3f16362efb 100644 --- a/crates/handler/src/lib.rs +++ b/crates/handler/src/lib.rs @@ -43,8 +43,7 @@ use context_interface::{ TransactionGetter, }; use handler_interface::{ - ExecutionHandler, Frame, FrameOrResultGen, Handler, PostExecutionHandler, PreExecutionHandler, - ValidationHandler, + ExecutionHandler, Handler, PostExecutionHandler, PreExecutionHandler, ValidationHandler, }; use interpreter::Host; diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index 1f35822ae9..84f2a90866 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -1,6 +1,5 @@ use context_interface::{Cfg, CfgGetter}; use handler_interface::PrecompileProvider; -use interpreter::Host; use interpreter::{Gas, InstructionResult, InterpreterResult}; use precompile::PrecompileErrors; use precompile::{PrecompileSpecId, Precompiles}; diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 393b30659f..e5f7ea55f6 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -26,8 +26,8 @@ all = "warn" revm.workspace = true # mics -auto_impl = { version = "1.2", default-features = false } -derive-where = { version = "1.2.7", default-features = false } +auto_impl.workspace = true +derive-where.workspace = true # Optional serde = { version = "1.0", default-features = false, features = [ diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 143c3938df..eaaaf35643 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -4,34 +4,33 @@ use std::rc::Rc; use auto_impl::auto_impl; use derive_where::derive_where; use revm::{ - bytecode::{opcode::OpCode, Bytecode, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}, + bytecode::opcode::OpCode, context::{block::BlockEnv, tx::TxEnv}, context_interface::{ journaled_state::{AccountLoad, Eip7702CodeLoad}, - result::{EVMError, InvalidTransaction}, + result::EVMError, Block, BlockGetter, CfgEnv, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, JournalStateGetterDBError, Transaction, TransactionGetter, }, database_interface::{Database, EmptyDB}, handler::{ - EthExecution, EthFrame, EthHandler, EthPostExecution, EthPreExecution, - EthPrecompileProvider, EthValidation, FrameResult, + EthExecution, EthFrame, EthHandler, EthPreExecution, EthPrecompileProvider, EthValidation, + FrameResult, }, handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}, interpreter::{ - as_u64_saturated, - instructions::{arithmetic::addmod, host, instruction}, - interpreter::{EthInstructionProvider, EthInterpreter, InstructionProvider}, - interpreter_wiring::{Jumps, MemoryTrait}, + instructions::host::{log, selfdestruct}, + interpreter::{EthInterpreter, InstructionProvider}, + interpreter_wiring::{Jumps, LoopControl, MemoryTrait}, table::{self, CustomInstruction}, - CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Host, Instruction, - InterpreterWire, NewFrameAction, NewInterpreter, SStoreResult, SelfDestructResult, - StateLoad, + CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, FrameInput, Host, + Instruction, InstructionResult, InterpreterWire, NewInterpreter, SStoreResult, + SelfDestructResult, StateLoad, }, precompile::PrecompileErrors, - primitives::{Address, Bytes, HashSet, Log, B256, BLOCK_HASH_HISTORY, U256}, + primitives::{Address, Bytes, Log, B256, U256}, specification::hardfork::SpecId, - Context, Error, Evm, JournaledState, + Context, Error, Evm, JournalEntry, JournaledState, }; /// EVM [Interpreter] callbacks. @@ -122,11 +121,11 @@ pub trait Inspector { &mut self, context: &mut Self::Context, inputs: &CallInputs, - outcome: CallOutcome, - ) -> CallOutcome { + outcome: &mut CallOutcome, + ) { let _ = context; let _ = inputs; - outcome + let _ = outcome; } /// Called when a contract is about to be created. @@ -154,11 +153,11 @@ pub trait Inspector { &mut self, context: &mut Self::Context, inputs: &CreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { let _ = context; let _ = inputs; - outcome + let _ = outcome; } /// Called when EOF creating is called. @@ -179,11 +178,11 @@ pub trait Inspector { &mut self, context: &mut Self::Context, inputs: &EOFCreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { let _ = context; let _ = inputs; - outcome + let _ = outcome; } /// Called when a contract has been self-destructed with funds transferred to target. @@ -223,7 +222,7 @@ impl Inspector for StepPrintInspector { fn step( &mut self, interp: &mut NewInterpreter, - context: &mut Self::Context, + _context: &mut Self::Context, ) { let opcode = interp.bytecode.opcode(); let name = OpCode::name_by_op(opcode); @@ -259,8 +258,12 @@ pub trait InspectorCtx { type IW: InterpreterWire; fn step(&mut self, interp: &mut NewInterpreter); - fn step_end(&mut self, interp: &mut NewInterpreter); + fn initialize_interp(&mut self, interp: &mut NewInterpreter); + fn frame_start(&mut self, frame_input: &mut FrameInput) -> Option; + fn frame_end(&mut self, frame_output: &mut FrameResult); + fn inspector_selfdestruct(&mut self, contract: Address, target: Address, value: U256); + fn inspector_log(&mut self, interp: &mut NewInterpreter, log: &Log); } impl GetInspector for INSP { @@ -283,6 +286,7 @@ pub struct InspectorContext< > { pub inner: Context, pub inspector: INSP, + pub frame_input_stack: Vec, } impl Host @@ -389,6 +393,73 @@ where .get_inspector() .step_end(interp, &mut self.inner); } + + fn initialize_interp(&mut self, interp: &mut NewInterpreter) { + self.inspector + .get_inspector() + .initialize_interp(interp, &mut self.inner); + } + fn inspector_log(&mut self, interp: &mut NewInterpreter, 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 ctx = &mut self.inner; + match frame_input { + FrameInput::Call(i) => { + if let Some(output) = insp.call(ctx, i) { + return Some(FrameResult::Call(output)); + } + } + FrameInput::Create(i) => { + if let Some(output) = insp.create(ctx, i) { + return Some(FrameResult::Create(output)); + } + } + FrameInput::EOFCreate(i) => { + if let Some(output) = insp.eofcreate(ctx, 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 ctx = &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(ctx, &i, outcome); + } + FrameResult::Create(outcome) => { + let FrameInput::Create(i) = frame_input else { + panic!("FrameInput::Create expected"); + }; + insp.create_end(ctx, &i, outcome); + } + FrameResult::EOFCreate(outcome) => { + let FrameInput::EOFCreate(i) = frame_input else { + panic!("FrameInput::EofCreate expected"); + }; + insp.eofcreate_end(ctx, &i, outcome); + } + } + } + + fn inspector_selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + self.inspector + .get_inspector() + .selfdestruct(contract, target, value) + } } impl JournalStateGetter @@ -440,6 +511,16 @@ impl BlockGetter } } +impl JournalExtGetter + for InspectorContext +{ + type JournalExt = JournaledState; + + fn journal_ext(&self) -> &Self::JournalExt { + &self.inner.journaled_state + } +} + #[derive(Clone)] pub struct InspectorInstruction { pub instruction: fn(&mut NewInterpreter, &mut HOST), @@ -480,6 +561,29 @@ 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; +} + /* INSPECTOR FEATURES: - [x] Step/StepEnd (Step/StepEnd are wrapped inside InspectorInstructionProvider) @@ -496,13 +600,12 @@ INSPECTOR FEATURES: impl InstructionProvider for InspectorInstructionProvider where WIRE: InterpreterWire, - HOST: Host + InspectorCtx, + HOST: Host + JournalExtGetter + JournalStateGetter + InspectorCtx, { type WIRE = WIRE; type Host = HOST; fn new(_ctx: &mut Self::Host) -> Self { - // TODO make this configurable. Inspection over same instruction is not useful. let main_table = table::make_instruction_table::(); let mut table: [MaybeUninit>; 256] = unsafe { MaybeUninit::uninit().assume_init() }; @@ -514,10 +617,75 @@ where *element = MaybeUninit::new(foo); } + let mut table = + unsafe { core::mem::transmute::<_, [InspectorInstruction; 256]>(table) }; + + // inspector log wrapper + + fn inspector_log( + interpreter: &mut NewInterpreter<::IW>, + ctx: &mut CTX, + prev: Instruction<::IW, CTX>, + ) { + prev(interpreter, ctx); + + if interpreter.control.instruction_result() == InstructionResult::Continue { + let last_log = ctx.journal_ext().logs().last().unwrap().clone(); + ctx.inspector_log(interpreter, &last_log); + } + } + /* LOG and Selfdestruct instructions */ + table[OpCode::LOG0.as_usize()] = InspectorInstruction { + instruction: |interp, ctx| { + inspector_log(interp, ctx, log::<0, HOST>); + }, + }; + table[OpCode::LOG1.as_usize()] = InspectorInstruction { + instruction: |interp, ctx| { + inspector_log(interp, ctx, log::<1, HOST>); + }, + }; + table[OpCode::LOG2.as_usize()] = InspectorInstruction { + instruction: |interp, ctx| { + inspector_log(interp, ctx, log::<2, HOST>); + }, + }; + table[OpCode::LOG3.as_usize()] = InspectorInstruction { + instruction: |interp, ctx| { + inspector_log(interp, ctx, log::<3, HOST>); + }, + }; + table[OpCode::LOG4.as_usize()] = InspectorInstruction { + instruction: |interp, ctx| { + inspector_log(interp, ctx, log::<4, HOST>); + }, + }; + + table[OpCode::SELFDESTRUCT.as_usize()] = InspectorInstruction { + instruction: |interp, ctx| { + selfdestruct::(interp, ctx); + if interp.control.instruction_result() == InstructionResult::SelfDestruct { + match ctx.journal_ext().last_journal().last() { + Some(JournalEntry::AccountDestroyed { + address, + target, + had_balance, + .. + }) => { + ctx.inspector_selfdestruct(*address, *target, *had_balance); + } + Some(JournalEntry::BalanceTransfer { + from, to, balance, .. + }) => { + ctx.inspector_selfdestruct(*from, *to, *balance); + } + _ => {} + } + } + }, + }; - let table = - unsafe { core::mem::transmute::<_, [InspectorInstruction; 256]>(table) }; Self { instruction_table: Rc::new(table), } @@ -550,6 +718,7 @@ where + BlockGetter + JournalStateGetter + CfgGetter + + JournalExtGetter + Host + InspectorCtx, ERROR: From> + From, @@ -557,25 +726,56 @@ where { type Context = CTX; type Error = ERROR; - type FrameInit = NewFrameAction; + type FrameInit = FrameInput; type FrameResult = FrameResult; fn init_first( - cxt: &mut Self::Context, - frame_action: Self::FrameInit, + ctx: &mut Self::Context, + mut frame_input: Self::FrameInit, ) -> Result, Self::Error> { - EthFrame::init_first(cxt, frame_action) - .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })) + if let Some(output) = ctx.frame_start(&mut frame_input) { + return Ok(FrameOrResultGen::Result(output)); + } + let mut ret = EthFrame::init_first(ctx, frame_input) + .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })); + + match &mut ret { + Ok(FrameOrResultGen::Result(res)) => { + ctx.frame_end(res); + } + Ok(FrameOrResultGen::Frame(frame)) => { + ctx.initialize_interp(&mut frame.eth_frame.interpreter); + } + _ => (), + } + + ret } fn init( &self, - cxt: &mut Self::Context, - frame_action: Self::FrameInit, + ctx: &mut Self::Context, + mut frame_input: Self::FrameInit, ) -> Result, Self::Error> { - self.eth_frame - .init(cxt, frame_action) - .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })) + if let Some(output) = ctx.frame_start(&mut frame_input) { + return Ok(FrameOrResultGen::Result(output)); + } + let mut ret = self + .eth_frame + .init(ctx, frame_input) + .map(|frame| frame.map_frame(|eth_frame| Self { eth_frame })); + + match &mut ret { + Ok(FrameOrResultGen::Result(res)) => { + ctx.frame_end(res); + } + Ok(FrameOrResultGen::Frame(frame)) => { + ctx.initialize_interp(&mut frame.eth_frame.interpreter); + } + _ => (), + } + + ret } fn run( @@ -587,10 +787,11 @@ where fn return_result( &mut self, - cxt: &mut Self::Context, - result: Self::FrameResult, + ctx: &mut Self::Context, + mut result: Self::FrameResult, ) -> Result<(), Self::Error> { - self.eth_frame.return_result(cxt, result) + ctx.frame_end(&mut result); + self.eth_frame.return_result(ctx, result) } } diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 8178cd8774..231d892843 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -28,9 +28,6 @@ primitives.workspace = true specification.workspace = true context-interface.workspace = true -# mics -derive-where = { version = "1.2.7", default-features = false } - # optional serde = { version = "1.0", default-features = false, features = [ "derive", diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index cfde978b23..a4c7281944 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -6,7 +6,7 @@ use crate::{ gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD, MIN_CALLEE_GAS}, instructions::utility::IntoAddress, interpreter::NewInterpreter, - interpreter_action::NewFrameAction, + interpreter_action::FrameInput, interpreter_wiring::{ EofContainer, Immediates, InputsTrait, InterpreterWire, Jumps, LoopControl, MemoryTrait, ReturnData, RuntimeFlag, StackTrait, @@ -74,7 +74,7 @@ pub fn eofcreate( gas!(interpreter, gas_limit); // Send container for execution container is preverified. interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::EOFCreate(Box::new( + InterpreterAction::NewFrame(FrameInput::EOFCreate(Box::new( EOFCreateInputs::new_opcode( interpreter.input.target_address(), created_address, @@ -272,7 +272,7 @@ pub fn extcall( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address, @@ -310,7 +310,7 @@ pub fn extdelegatecall( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address: interpreter.input.target_address(), @@ -348,7 +348,7 @@ pub fn extstaticcall( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address, @@ -428,7 +428,7 @@ pub fn create( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Create(Box::new(CreateInputs { + InterpreterAction::NewFrame(FrameInput::Create(Box::new(CreateInputs { caller: interpreter.input.target_address(), scheme, value, @@ -481,7 +481,7 @@ pub fn call( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address: to, @@ -535,7 +535,7 @@ pub fn call_code( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address: interpreter.input.target_address(), @@ -583,7 +583,7 @@ pub fn delegate_call( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address: interpreter.input.target_address(), @@ -630,7 +630,7 @@ pub fn static_call( // Call host to interact with target contract interpreter.control.set_next_action( - InterpreterAction::NewFrame(NewFrameAction::Call(Box::new(CallInputs { + InterpreterAction::NewFrame(FrameInput::Call(Box::new(CallInputs { input, gas_limit, target_address: to, diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 5ade7dc4c6..b4c65b7e31 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -37,8 +37,8 @@ macro_rules! require_non_staticcall { #[macro_export] macro_rules! otry { - ($expresion: expr) => {{ - let Some(value) = $expresion else { + ($expression: expr) => {{ + let Some(value) = $expression else { return; }; value diff --git a/crates/interpreter/src/interpreter_action.rs b/crates/interpreter/src/interpreter_action.rs index 67b382d7d6..eca98dc4e7 100644 --- a/crates/interpreter/src/interpreter_action.rs +++ b/crates/interpreter/src/interpreter_action.rs @@ -15,7 +15,7 @@ use std::boxed::Box; #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum NewFrameAction { +pub enum FrameInput { /// CALL, CALLCODE, DELEGATECALL, STATICCALL /// or EOF EXT*CALL instruction called. Call(Box), @@ -25,7 +25,7 @@ pub enum NewFrameAction { EOFCreate(Box), } -impl AsMut for NewFrameAction { +impl AsMut for FrameInput { fn as_mut(&mut self) -> &mut Self { self } @@ -35,7 +35,7 @@ impl AsMut for NewFrameAction { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InterpreterAction { /// New frame - NewFrame(NewFrameAction), + NewFrame(FrameInput), /// Interpreter finished execution. Return { result: InterpreterResult }, /// No action @@ -46,15 +46,12 @@ pub enum InterpreterAction { impl InterpreterAction { /// Returns true if action is call. pub fn is_call(&self) -> bool { - matches!(self, InterpreterAction::NewFrame(NewFrameAction::Call(..))) + matches!(self, InterpreterAction::NewFrame(FrameInput::Call(..))) } /// Returns true if action is create. pub fn is_create(&self) -> bool { - matches!( - self, - InterpreterAction::NewFrame(NewFrameAction::Create(..)) - ) + matches!(self, InterpreterAction::NewFrame(FrameInput::Create(..))) } /// Returns true if action is return. diff --git a/crates/interpreter/src/interpreter_wiring.rs b/crates/interpreter/src/interpreter_wiring.rs index 9493373c69..442ee1e36e 100644 --- a/crates/interpreter/src/interpreter_wiring.rs +++ b/crates/interpreter/src/interpreter_wiring.rs @@ -39,7 +39,7 @@ pub trait Jumps { /// Absolute jumps require checking for overflow and if target is a jump destination /// from jump table. fn absolute_jump(&mut self, offset: usize); - /// Check legacy jump destionation from jump table. + /// Check legacy jump destination from jump table. fn is_valid_legacy_jump(&mut self, offset: usize) -> bool; /// Return current program counter. fn pc(&self) -> usize; diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index a3a212ea35..18ecd4f88e 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -37,7 +37,7 @@ pub use interpreter::{ }; pub use interpreter_action::{ CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, EOFCreateInputs, - EOFCreateKind, InterpreterAction, NewFrameAction, + EOFCreateKind, FrameInput, InterpreterAction, }; pub use interpreter_wiring::InterpreterWire; pub use specification::constants::{MAX_CODE_SIZE, MAX_INITCODE_SIZE}; diff --git a/crates/interpreter/src/table.rs b/crates/interpreter/src/table.rs index 81cfa8e442..f4c344cde6 100644 --- a/crates/interpreter/src/table.rs +++ b/crates/interpreter/src/table.rs @@ -6,8 +6,6 @@ use crate::{ interpreter_wiring::InterpreterWire, Host, }; -use specification::hardfork::Spec; -use std::boxed::Box; /// EVM opcode function signature. pub type Instruction = for<'a> fn(&'a mut NewInterpreter, &'a mut H); diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index cc79a2d664..e2445b2a03 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -67,7 +67,6 @@ p256 = { version = "0.13.2", optional = true, default-features = false, features # utils cfg-if = { version = "1.0", default-features = false } -dyn-clone = "1.0" [dev-dependencies] criterion = "0.5" diff --git a/crates/precompile/benches/bench.rs b/crates/precompile/benches/bench.rs index 8b68e042c3..38513a68fd 100644 --- a/crates/precompile/benches/bench.rs +++ b/crates/precompile/benches/bench.rs @@ -1,4 +1,3 @@ -use context_interface::CfgEnv; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use primitives::{hex, keccak256, U256}; use revm_precompile::{ diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index b6e0947c4a..1a418b76d5 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -1,7 +1,7 @@ use context_interface::result::EVMError; use core::fmt; use primitives::Bytes; -use std::string::String; +use std::string::{String, ToString}; /// A precompile operation result. /// diff --git a/crates/precompile/src/secp256r1.rs b/crates/precompile/src/secp256r1.rs index 16aaebec31..6f6bb84f96 100644 --- a/crates/precompile/src/secp256r1.rs +++ b/crates/precompile/src/secp256r1.rs @@ -7,8 +7,7 @@ //! P256 elliptic curve. The [`P256VERIFY`] const represents the implementation of this precompile, //! with the address that it is currently deployed at. use crate::{ - u64_to_address, Precompile, PrecompileError, PrecompileOutput, PrecompileResult, - PrecompileWithAddress, + u64_to_address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, }; use p256::ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey}; use primitives::{Bytes, B256}; @@ -23,7 +22,7 @@ pub fn precompiles() -> impl Iterator { /// [EIP-7212](https://eips.ethereum.org/EIPS/eip-7212#specification) secp256r1 precompile. pub const P256VERIFY: PrecompileWithAddress = - PrecompileWithAddress(u64_to_address(0x100), Precompile::Standard(p256_verify)); + PrecompileWithAddress(u64_to_address(0x100), p256_verify); /// secp256r1 precompile logic. It takes the input bytes sent to the precompile /// and the gas limit. The output represents the result of verifying the diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 3a22df1e52..2b837c8460 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -37,10 +37,11 @@ handler.workspace = true handler-interface.workspace = true # Optional -serde = { version = "1.0", default-features = false, features = [ - "derive", - "rc", -], optional = true } +# TODO check if needed. +# serde = { version = "1.0", default-features = false, features = [ +# "derive", +# "rc", +# ], optional = true } [dev-dependencies] database.workspace = true @@ -58,10 +59,9 @@ alloy-provider = "0.4.2" [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst"] -std = ["serde?/std", "interpreter/std", "precompile/std"] +std = ["interpreter/std", "precompile/std"] hashbrown = ["interpreter/hashbrown", "precompile/hashbrown"] serde = [ - "dep:serde", "interpreter/serde", "database-interface/serde", "primitives/serde", diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 5a1923e204..4f1690c844 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,18 +6,12 @@ use context_interface::{ JournalStateGetterDBError, Transaction, TransactionGetter, }; use database_interface::Database; -use handler::{ - EthExecution, EthFrame, EthHandler, EthPreExecution, EthPrecompileProvider, EthValidation, - FrameResult, -}; +use handler::{EthHandler, FrameResult}; use handler_interface::{ ExecutionHandler, Frame, FrameOrResultGen, Handler, PostExecutionHandler, PreExecutionHandler, ValidationHandler, }; -use interpreter::{ - interpreter::{EthInstructionProvider, EthInterpreter}, - Host, -}; +use interpreter::Host; use precompile::PrecompileErrors; use primitives::Log; use specification::hardfork::SpecId; @@ -25,37 +19,20 @@ use state::EvmState; use std::vec::Vec; /// Main EVM structure -pub struct Evm> { +pub struct Evm> { pub context: CTX, - pub handler: HAND, + pub handler: HANDLER, pub _error: std::marker::PhantomData ERROR>, } +/// Mainnet Error. pub type Error = EVMError<::Error, InvalidTransaction>; +/// Mainnet Contexts. pub type EthContext = Context; -pub type MainEvm = Evm< - Error, - EthContext, - EthHandler< - EthContext, - Error, - EthValidation, Error>, - EthPreExecution, Error>, - EthExecution< - EthContext, - Error, - EthFrame< - EthContext, - Error, - EthInterpreter<()>, - EthPrecompileProvider, Error>, - EthInstructionProvider, EthContext>, - >, - >, - >, ->; +/// Mainnet EVM type. +pub type MainEvm = Evm, EthContext>; impl Evm> diff --git a/crates/wiring/transaction/Cargo.toml b/crates/wiring/transaction/Cargo.toml index 5dfd154e00..b9a43b3950 100644 --- a/crates/wiring/transaction/Cargo.toml +++ b/crates/wiring/transaction/Cargo.toml @@ -33,7 +33,7 @@ serde = { version = "1.0", default-features = false, features = [ ], optional = true } # mics -auto_impl = "1.2" +auto_impl.workspace = true [features] default = ["std"] diff --git a/examples/database_components/Cargo.toml b/examples/database_components/Cargo.toml index 03139b79ab..5e1fe4bd61 100644 --- a/examples/database_components/Cargo.toml +++ b/examples/database_components/Cargo.toml @@ -26,4 +26,4 @@ all = "warn" revm.workspace = true # mics -auto_impl = "1.2" +auto_impl.workspace = true diff --git a/graph.png b/graph.png index 79442a7a27..4ae64afc9a 100644 Binary files a/graph.png and b/graph.png differ