From f8fcaa7b91f54507d61f00d77bbec91930d8f76b Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 1 May 2024 22:00:36 +0000 Subject: [PATCH 01/59] refactor: allow chain-specific configuration of Evm --- Cargo.lock | 2 +- bins/revme/src/cmd/statetest/runner.rs | 23 +- crates/interpreter/Cargo.toml | 8 - crates/interpreter/src/host.rs | 14 +- crates/interpreter/src/host/dummy.rs | 20 +- crates/interpreter/src/instruction_result.rs | 76 +- .../interpreter/src/instructions/bitwise.rs | 10 +- .../interpreter/src/instructions/control.rs | 18 +- crates/interpreter/src/instructions/data.rs | 6 +- .../interpreter/src/instructions/host_env.rs | 26 +- crates/interpreter/src/instructions/stack.rs | 8 +- crates/interpreter/src/instructions/system.rs | 6 +- crates/interpreter/src/interpreter.rs | 16 +- .../interpreter/src/interpreter/contract.rs | 24 +- .../src/interpreter_action/call_inputs.rs | 16 +- .../src/interpreter_action/create_inputs.rs | 16 +- .../interpreter_action/eof_create_inputs.rs | 12 +- crates/interpreter/src/opcode.rs | 78 +- crates/precompile/Cargo.toml | 8 - crates/precompile/benches/bench.rs | 4 +- crates/precompile/src/fatal_precompile.rs | 4 +- crates/precompile/src/kzg_point_evaluation.rs | 8 +- crates/precompile/src/lib.rs | 4 - crates/primitives/Cargo.toml | 3 - crates/primitives/src/block.rs | 67 ++ crates/primitives/src/chain_spec.rs | 57 ++ crates/primitives/src/env.rs | 272 +++--- crates/primitives/src/env/handler_cfg.rs | 159 ---- crates/primitives/src/lib.rs | 6 + crates/primitives/src/precompile.rs | 24 +- crates/primitives/src/result.rs | 51 +- crates/primitives/src/specification.rs | 295 +------ crates/primitives/src/transaction.rs | 82 ++ crates/revm/Cargo.toml | 14 +- crates/revm/benches/bench.rs | 14 +- crates/revm/src/builder.rs | 382 +++++---- crates/revm/src/context.rs | 52 +- .../revm/src/context/context_precompiles.rs | 80 +- crates/revm/src/context/evm_context.rs | 99 ++- crates/revm/src/context/inner_evm_context.rs | 67 +- crates/revm/src/custom_upcode.rs | 260 ++++++ crates/revm/src/evm.rs | 124 +-- crates/revm/src/handler.rs | 187 ++--- crates/revm/src/handler/cfg.rs | 78 ++ .../src/handler/handle_types/execution.rs | 163 ++-- .../handler/handle_types/post_execution.rs | 82 +- .../src/handler/handle_types/pre_execution.rs | 53 +- .../src/handler/handle_types/validation.rs | 52 +- crates/revm/src/handler/mainnet/execution.rs | 102 ++- .../src/handler/mainnet/post_execution.rs | 49 +- .../revm/src/handler/mainnet/pre_execution.rs | 59 +- crates/revm/src/handler/mainnet/validation.rs | 42 +- crates/revm/src/handler/register.rs | 22 +- crates/revm/src/inspector.rs | 33 +- crates/revm/src/inspector/customprinter.rs | 22 +- crates/revm/src/inspector/eip3155.rs | 24 +- crates/revm/src/inspector/gas.rs | 78 +- crates/revm/src/inspector/handler_register.rs | 82 +- crates/revm/src/inspector/noop.rs | 4 +- crates/revm/src/journaled_state.rs | 46 +- crates/revm/src/lib.rs | 4 +- crates/revm/src/optimism.rs | 10 +- crates/revm/src/optimism/env.rs | 171 ++++ crates/revm/src/optimism/handler.rs | 19 + crates/revm/src/optimism/handler_register.rs | 360 ++++---- crates/revm/src/optimism/l1block.rs | 71 +- crates/revm/src/optimism/result.rs | 100 +++ crates/revm/src/optimism/spec.rs | 791 ++++++++++++++++++ examples/db_by_ref.rs | 8 +- 69 files changed, 3317 insertions(+), 1910 deletions(-) create mode 100644 crates/primitives/src/block.rs create mode 100644 crates/primitives/src/chain_spec.rs delete mode 100644 crates/primitives/src/env/handler_cfg.rs create mode 100644 crates/primitives/src/transaction.rs create mode 100644 crates/revm/src/custom_upcode.rs create mode 100644 crates/revm/src/handler/cfg.rs create mode 100644 crates/revm/src/optimism/env.rs create mode 100644 crates/revm/src/optimism/handler.rs create mode 100644 crates/revm/src/optimism/result.rs create mode 100644 crates/revm/src/optimism/spec.rs diff --git a/Cargo.lock b/Cargo.lock index 77a5fe7486..2d7a0ba379 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3013,9 +3013,9 @@ dependencies = [ "alloy-transport", "anyhow", "auto_impl", - "cfg-if", "criterion", "dyn-clone", + "enumn", "ethers-contract", "ethers-core", "ethers-providers", diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 0907a94bb2..5a9846257f 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -28,6 +28,11 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; +#[cfg(feature = "optimism")] +type TestChainSpec = revm::optimism::OptimismChainSpec; +#[cfg(not(feature = "optimism"))] +type TestChainSpec = revm::primitives::EthChainSpec; + #[derive(Debug, Error)] #[error("Test {name} failed: {kind}")] pub struct TestError { @@ -130,8 +135,8 @@ fn check_evm_execution( test: &Test, expected_output: Option<&Bytes>, test_name: &str, - exec_result: &EVMResultGeneric, - evm: &Evm<'_, EXT, &mut State>, + exec_result: &EVMResultGeneric, TestChainSpec, Infallible>, + evm: &Evm<'_, TestChainSpec, EXT, &mut State>, print_json_outcome: bool, ) -> Result<(), TestError> { let logs_root = log_rlp_hash(exec_result.as_ref().map(|r| r.logs()).unwrap_or_default()); @@ -155,7 +160,7 @@ fn check_evm_execution( Err(e) => e.to_string(), }, "postLogsHash": logs_root, - "fork": evm.handler.cfg().spec_id, + "fork": evm.handler.spec_id(), "test": test_name, "d": test.indexes.data, "g": test.indexes.gas, @@ -268,7 +273,7 @@ pub fn execute_test_suite( cache_state.insert_account_with_storage(address, acc_info, info.storage); } - let mut env = Box::::default(); + let mut env = Box::>::default(); // for mainnet env.cfg.chain_id = 1; // env.cfg.spec_id is set down the road @@ -357,10 +362,7 @@ pub fn execute_test_suite( env.tx.transact_to = to; let mut cache = cache_state.clone(); - cache.set_state_clear_flag(SpecId::enabled( - spec_id, - revm::primitives::SpecId::SPURIOUS_DRAGON, - )); + cache.set_state_clear_flag(SpecId::enabled(spec_id, SpecId::SPURIOUS_DRAGON)); let mut state = revm::db::State::builder() .with_cached_prestate(cache) .with_bundle_update() @@ -426,10 +428,7 @@ pub fn execute_test_suite( // re build to run with tracing let mut cache = cache_state.clone(); - cache.set_state_clear_flag(SpecId::enabled( - spec_id, - revm::primitives::SpecId::SPURIOUS_DRAGON, - )); + cache.set_state_clear_flag(SpecId::enabled(spec_id, SpecId::SPURIOUS_DRAGON)); let state = revm::db::State::builder() .with_cached_prestate(cache) .with_bundle_update() diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index e2e6f3e851..8b97e9d3db 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -51,14 +51,6 @@ portable = ["revm-primitives/portable"] parse = ["dep:paste", "dep:phf"] optimism = ["revm-primitives/optimism"] -# Optimism default handler enabled Optimism handler register by default in EvmBuilder. -optimism-default-handler = [ - "optimism", - "revm-primitives/optimism-default-handler", -] -negate-optimism-default-handler = [ - "revm-primitives/negate-optimism-default-handler", -] dev = [ "memory_limit", diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index e07cb31637..4dc65b5172 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -2,14 +2,18 @@ use crate::primitives::{Address, Bytes, Env, Log, B256, U256}; mod dummy; pub use dummy::DummyHost; +use revm_primitives::ChainSpec; /// EVM context host. pub trait Host { + /// Chain specification. + type ChainSpecT: ChainSpec; + /// Returns a reference to the environment. - fn env(&self) -> &Env; + fn env(&self) -> &Env; /// Returns a mutable reference to the environment. - fn env_mut(&mut self) -> &mut Env; + fn env_mut(&mut self) -> &mut Env; /// Load an account. /// @@ -84,13 +88,15 @@ pub struct SelfDestructResult { #[cfg(test)] mod tests { + use revm_primitives::EthChainSpec; + use super::*; fn assert_host() {} #[test] fn object_safety() { - assert_host::(); - assert_host::(); + assert_host::>(); + assert_host::>(); } } diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index dba5020941..9ee85d1b65 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,5 +1,7 @@ use crate::{ - primitives::{hash_map::Entry, Address, Bytes, Env, HashMap, Log, B256, KECCAK_EMPTY, U256}, + primitives::{ + hash_map::Entry, Address, Bytes, ChainSpec, Env, HashMap, Log, B256, KECCAK_EMPTY, U256, + }, Host, SStoreResult, SelfDestructResult, }; use std::vec::Vec; @@ -8,17 +10,17 @@ use super::LoadAccountResult; /// A dummy [Host] implementation. #[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct DummyHost { - pub env: Env, +pub struct DummyHost { + pub env: Env, pub storage: HashMap, pub transient_storage: HashMap, pub log: Vec, } -impl DummyHost { +impl DummyHost { /// Create a new dummy host with the given [`Env`]. #[inline] - pub fn new(env: Env) -> Self { + pub fn new(env: Env) -> Self { Self { env, ..Default::default() @@ -33,14 +35,16 @@ impl DummyHost { } } -impl Host for DummyHost { +impl Host for DummyHost { + type ChainSpecT = ChainSpecT; + #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &Env { &self.env } #[inline] - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut Env { &mut self.env } diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index 0cdc694c6f..0e3871c474 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -1,3 +1,5 @@ +use revm_primitives::ChainSpec; + use crate::primitives::{HaltReason, OutOfGasError, SuccessReason}; #[repr(u8)] @@ -111,8 +113,6 @@ impl From for InstructionResult { HaltReason::EofAuxDataOverflow => Self::EofAuxDataOverflow, HaltReason::EofAuxDataTooSmall => Self::EofAuxDataTooSmall, HaltReason::EOFFunctionStackOverflow => Self::EOFFunctionStackOverflow, - #[cfg(feature = "optimism")] - HaltReason::FailedDeposit => Self::FatalExternalError, } } } @@ -210,15 +210,15 @@ pub enum InternalResult { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum SuccessOrHalt { +pub enum SuccessOrHalt { Success(SuccessReason), Revert, - Halt(HaltReason), + Halt(ChainSpecT::HaltReason), FatalExternalError, Internal(InternalResult), } -impl SuccessOrHalt { +impl SuccessOrHalt { /// Returns true if the transaction returned successfully without halts. #[inline] pub fn is_success(self) -> bool { @@ -248,7 +248,7 @@ impl SuccessOrHalt { /// Returns the [HaltReason] value the EVM has experienced an exceptional halt #[inline] - pub fn to_halt(self) -> Option { + pub fn to_halt(self) -> Option { match self { SuccessOrHalt::Halt(reason) => Some(reason), _ => None, @@ -256,7 +256,7 @@ impl SuccessOrHalt { } } -impl From for SuccessOrHalt { +impl From for SuccessOrHalt { fn from(result: InstructionResult) -> Self { match result { InstructionResult::Continue => Self::Internal(InternalResult::InternalContinue), // used only in interpreter loop @@ -266,55 +266,65 @@ impl From for SuccessOrHalt { InstructionResult::Revert => Self::Revert, InstructionResult::CreateInitCodeStartingEF00 => Self::Revert, InstructionResult::CallOrCreate => Self::Internal(InternalResult::InternalCallOrCreate), // used only in interpreter loop - InstructionResult::CallTooDeep => Self::Halt(HaltReason::CallTooDeep), // not gonna happen for first call - InstructionResult::OutOfFunds => Self::Halt(HaltReason::OutOfFunds), // Check for first call is done separately. - InstructionResult::OutOfGas => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Basic)), + InstructionResult::CallTooDeep => Self::Halt(HaltReason::CallTooDeep.into()), // not gonna happen for first call + InstructionResult::OutOfFunds => Self::Halt(HaltReason::OutOfFunds.into()), // Check for first call is done separately. + InstructionResult::OutOfGas => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::Basic).into()) + } InstructionResult::MemoryLimitOOG => { - Self::Halt(HaltReason::OutOfGas(OutOfGasError::MemoryLimit)) + Self::Halt(HaltReason::OutOfGas(OutOfGasError::MemoryLimit).into()) + } + InstructionResult::MemoryOOG => { + Self::Halt(HaltReason::OutOfGas(OutOfGasError::Memory).into()) } - InstructionResult::MemoryOOG => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Memory)), InstructionResult::PrecompileOOG => { - Self::Halt(HaltReason::OutOfGas(OutOfGasError::Precompile)) + Self::Halt(HaltReason::OutOfGas(OutOfGasError::Precompile).into()) } InstructionResult::InvalidOperandOOG => { - Self::Halt(HaltReason::OutOfGas(OutOfGasError::InvalidOperand)) + Self::Halt(HaltReason::OutOfGas(OutOfGasError::InvalidOperand).into()) } InstructionResult::OpcodeNotFound | InstructionResult::ReturnContractInNotInitEOF => { - Self::Halt(HaltReason::OpcodeNotFound) + Self::Halt(HaltReason::OpcodeNotFound.into()) } InstructionResult::CallNotAllowedInsideStatic => { - Self::Halt(HaltReason::CallNotAllowedInsideStatic) + Self::Halt(HaltReason::CallNotAllowedInsideStatic.into()) } // first call is not static call InstructionResult::StateChangeDuringStaticCall => { - Self::Halt(HaltReason::StateChangeDuringStaticCall) + Self::Halt(HaltReason::StateChangeDuringStaticCall.into()) } - InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode), - InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump), - InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated), - InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow), - InstructionResult::StackOverflow => Self::Halt(HaltReason::StackOverflow), - InstructionResult::OutOfOffset => Self::Halt(HaltReason::OutOfOffset), - InstructionResult::CreateCollision => Self::Halt(HaltReason::CreateCollision), - InstructionResult::OverflowPayment => Self::Halt(HaltReason::OverflowPayment), // Check for first call is done separately. - InstructionResult::PrecompileError => Self::Halt(HaltReason::PrecompileError), - InstructionResult::NonceOverflow => Self::Halt(HaltReason::NonceOverflow), + InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode.into()), + InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump.into()), + InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated.into()), + InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow.into()), + InstructionResult::StackOverflow => Self::Halt(HaltReason::StackOverflow.into()), + InstructionResult::OutOfOffset => Self::Halt(HaltReason::OutOfOffset.into()), + InstructionResult::CreateCollision => Self::Halt(HaltReason::CreateCollision.into()), + InstructionResult::OverflowPayment => Self::Halt(HaltReason::OverflowPayment.into()), // Check for first call is done separately. + InstructionResult::PrecompileError => Self::Halt(HaltReason::PrecompileError.into()), + InstructionResult::NonceOverflow => Self::Halt(HaltReason::NonceOverflow.into()), InstructionResult::CreateContractSizeLimit | InstructionResult::CreateContractStartingWithEF => { - Self::Halt(HaltReason::CreateContractSizeLimit) + Self::Halt(HaltReason::CreateContractSizeLimit.into()) } InstructionResult::CreateInitCodeSizeLimit => { - Self::Halt(HaltReason::CreateInitCodeSizeLimit) + Self::Halt(HaltReason::CreateInitCodeSizeLimit.into()) } // TODO (EOF) add proper Revert subtype. InstructionResult::InvalidEOFInitCode => Self::Revert, InstructionResult::FatalExternalError => Self::FatalExternalError, - InstructionResult::EOFOpcodeDisabledInLegacy => Self::Halt(HaltReason::OpcodeNotFound), + InstructionResult::EOFOpcodeDisabledInLegacy => { + Self::Halt(HaltReason::OpcodeNotFound.into()) + } InstructionResult::EOFFunctionStackOverflow => { - Self::Halt(HaltReason::EOFFunctionStackOverflow) + Self::Halt(HaltReason::EOFFunctionStackOverflow.into()) } InstructionResult::ReturnContract => Self::Success(SuccessReason::EofReturnContract), - InstructionResult::EofAuxDataOverflow => Self::Halt(HaltReason::EofAuxDataOverflow), - InstructionResult::EofAuxDataTooSmall => Self::Halt(HaltReason::EofAuxDataTooSmall), + InstructionResult::EofAuxDataOverflow => { + Self::Halt(HaltReason::EofAuxDataOverflow.into()) + } + InstructionResult::EofAuxDataTooSmall => { + Self::Halt(HaltReason::EofAuxDataTooSmall.into()) + } InstructionResult::InvalidEXTCALLTarget => { Self::Internal(InternalResult::InvalidEXTCALLTarget) } diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 8a87ee5ae0..068db1bccb 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -125,7 +125,7 @@ pub fn sar(interpreter: &mut Interpreter, _host: & mod tests { use crate::instructions::bitwise::{byte, sar, shl, shr}; use crate::{Contract, DummyHost, Interpreter}; - use revm_primitives::{uint, Env, LatestSpec, U256}; + use revm_primitives::{uint, Env, EthChainSpec, LatestSpec, U256}; #[test] fn test_shift_left() { @@ -202,7 +202,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shl::(&mut interpreter, &mut host); + shl::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -283,7 +283,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shr::(&mut interpreter, &mut host); + shr::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -389,7 +389,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - sar::(&mut interpreter, &mut host); + sar::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -403,7 +403,7 @@ mod tests { expected: U256, } - let mut host = DummyHost::new(Env::default()); + let mut host = DummyHost::new(Env::::default()); let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 40e9ace212..f625dd8c3a 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -206,7 +206,7 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { mod test { use std::sync::Arc; - use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, PragueSpec}; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, EthChainSpec, PragueSpec}; use super::*; use crate::{ @@ -216,7 +216,7 @@ mod test { #[test] fn rjump() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMP, 0x00, 0x02, STOP, STOP, @@ -230,7 +230,7 @@ mod test { #[test] fn rjumpi() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP, @@ -250,7 +250,7 @@ mod test { #[test] fn rjumpv() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPV, @@ -332,7 +332,7 @@ mod test { #[test] fn callf_retf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]); let bytes2 = Bytes::from([RETF]); @@ -363,7 +363,7 @@ mod test { #[test] fn callf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -387,7 +387,7 @@ mod test { #[test] fn callf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -404,7 +404,7 @@ mod test { #[test] fn jumpf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -425,7 +425,7 @@ mod test { #[test] fn jumpf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index dada108c1d..6fd5dfcf9b 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -83,7 +83,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { - use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, PragueSpec}; + use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, EthChainSpec, PragueSpec}; use std::sync::Arc; use super::*; @@ -107,7 +107,7 @@ mod test { #[test] fn dataload_dataloadn() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([ DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN, @@ -163,7 +163,7 @@ mod test { #[test] fn data_copy() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY])); diff --git a/crates/interpreter/src/instructions/host_env.rs b/crates/interpreter/src/instructions/host_env.rs index ce934d492f..2ffb25e34c 100644 --- a/crates/interpreter/src/instructions/host_env.rs +++ b/crates/interpreter/src/instructions/host_env.rs @@ -1,6 +1,6 @@ use crate::{ gas, - primitives::{Spec, SpecId::*, U256}, + primitives::{block, Block, Spec, SpecId::*, Transaction, U256}, Host, Interpreter, }; @@ -13,31 +13,31 @@ pub fn chainid(interpreter: &mut Interpreter, host pub fn coinbase(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push_b256!(interpreter, host.env().block.coinbase.into_word()); + push_b256!(interpreter, host.env().block.coinbase().into_word()); } pub fn timestamp(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push!(interpreter, host.env().block.timestamp); + push!(interpreter, *host.env().block.timestamp()); } pub fn block_number(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push!(interpreter, host.env().block.number); + push!(interpreter, *host.env().block.number()); } pub fn difficulty(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); if SPEC::enabled(MERGE) { - push_b256!(interpreter, host.env().block.prevrandao.unwrap()); + push_b256!(interpreter, *host.env().block.prevrandao().unwrap()); } else { - push!(interpreter, host.env().block.difficulty); + push!(interpreter, *host.env().block.difficulty()); } } pub fn gaslimit(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push!(interpreter, host.env().block.gas_limit); + push!(interpreter, *host.env().block.gas_limit()); } pub fn gasprice(interpreter: &mut Interpreter, host: &mut H) { @@ -49,12 +49,12 @@ pub fn gasprice(interpreter: &mut Interpreter, host: &mut H) { pub fn basefee(interpreter: &mut Interpreter, host: &mut H) { check!(interpreter, LONDON); gas!(interpreter, gas::BASE); - push!(interpreter, host.env().block.basefee); + push!(interpreter, *host.env().block.basefee()); } pub fn origin(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BASE); - push_b256!(interpreter, host.env().tx.caller.into_word()); + push_b256!(interpreter, host.env().tx.caller().into_word()); } // EIP-4844: Shard Blob Transactions @@ -63,7 +63,7 @@ pub fn blob_hash(interpreter: &mut Interpreter, ho gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, index); let i = as_usize_saturated!(index); - *index = match host.env().tx.blob_hashes.get(i) { + *index = match host.env().tx.blob_hashes().get(i) { Some(hash) => U256::from_be_bytes(hash.0), None => U256::ZERO, }; @@ -75,6 +75,10 @@ pub fn blob_basefee(interpreter: &mut Interpreter, gas!(interpreter, gas::BASE); push!( interpreter, - U256::from(host.env().block.get_blob_gasprice().unwrap_or_default()) + U256::from( + block::get_blob_gasprice(&host.env().block) + .copied() + .unwrap_or_default() + ) ); } diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index d75067e1f2..f39c0fb6c1 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -89,13 +89,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, DUPN, EXCHANGE, SWAPN}, - primitives::{Bytecode, Bytes, PragueSpec}, + primitives::{Bytecode, Bytes, EthChainSpec, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn dupn() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ DUPN, 0x00, DUPN, 0x01, DUPN, 0x02, @@ -115,7 +115,7 @@ mod test { #[test] fn swapn() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([SWAPN, 0x00, SWAPN, 0x01]))); @@ -135,7 +135,7 @@ mod test { #[test] fn exchange() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ EXCHANGE, 0x00, EXCHANGE, 0x11, diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 3605a53705..112d9fa156 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -189,13 +189,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, RETURNDATACOPY, RETURNDATALOAD}, - primitives::{bytes, Bytecode, PragueSpec}, + primitives::{bytes, Bytecode, EthChainSpec, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn returndataload() { - let table = make_instruction_table::<_, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( @@ -254,7 +254,7 @@ mod test { #[test] fn returndatacopy() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + let mut host = DummyHost::::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( [ diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index ea1389e7fe..c4e1598eea 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -469,20 +469,22 @@ pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) mod tests { use super::*; use crate::{opcode::InstructionTable, DummyHost}; - use revm_primitives::CancunSpec; + use revm_primitives::{CancunSpec, EthChainSpec}; #[test] fn object_safety() { let mut interp = Interpreter::new(Contract::default(), u64::MAX, false); - let mut host = crate::DummyHost::default(); - let table: &InstructionTable = - &crate::opcode::make_instruction_table::(); + let mut host = crate::DummyHost::::default(); + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::, CancunSpec>(); let _ = interp.run(EMPTY_SHARED_MEMORY, table, &mut host); - let host: &mut dyn Host = &mut host as &mut dyn Host; - let table: &InstructionTable = - &crate::opcode::make_instruction_table::(); + let host: &mut dyn Host = + &mut host as &mut dyn Host; + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::, CancunSpec>( + ); let _ = interp.run(EMPTY_SHARED_MEMORY, table, host); } } diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 304b700446..21c4080792 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,8 +1,8 @@ -use revm_primitives::TxKind; +use revm_primitives::ChainSpec; use super::analysis::to_analysed; use crate::{ - primitives::{Address, Bytecode, Bytes, Env, B256, U256}, + primitives::{Address, Bytecode, Bytes, Env, Transaction, TxKind, B256, U256}, CallInputs, }; @@ -55,23 +55,27 @@ impl Contract { /// Creates a new contract from the given [`Env`]. #[inline] - pub fn new_env(env: &Env, bytecode: Bytecode, hash: Option) -> Self { - let contract_address = match env.tx.transact_to { - TxKind::Call(caller) => caller, + pub fn new_env( + env: &Env, + bytecode: Bytecode, + hash: Option, + ) -> Self { + let contract_address = match env.tx.transact_to() { + TxKind::Call(caller) => *caller, TxKind::Create => Address::ZERO, }; - let bytecode_address = match env.tx.transact_to { - TxKind::Call(caller) => Some(caller), + let bytecode_address = match env.tx.transact_to() { + TxKind::Call(caller) => Some(*caller), TxKind::Create => None, }; Self::new( - env.tx.data.clone(), + env.tx.data().clone(), bytecode, hash, contract_address, bytecode_address, - env.tx.caller, - env.tx.value, + *env.tx.caller(), + *env.tx.value(), ) } diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index bc51ceac8d..b71e9c14e0 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -1,4 +1,6 @@ -use crate::primitives::{Address, Bytes, TxEnv, TxKind, U256}; +use revm_primitives::Transaction; + +use crate::primitives::{Address, Bytes, TxKind, U256}; use core::ops::Range; use std::boxed::Box; @@ -46,17 +48,17 @@ impl CallInputs { /// Creates new call inputs. /// /// Returns `None` if the transaction is not a call. - pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { - let TxKind::Call(target_address) = tx_env.transact_to else { + pub fn new(tx_env: &impl Transaction, gas_limit: u64) -> Option { + let TxKind::Call(target_address) = *tx_env.transact_to() else { return None; }; Some(CallInputs { - input: tx_env.data.clone(), + input: tx_env.data().clone(), gas_limit, target_address, bytecode_address: target_address, - caller: tx_env.caller, - value: CallValue::Transfer(tx_env.value), + caller: *tx_env.caller(), + value: CallValue::Transfer(*tx_env.value()), scheme: CallScheme::Call, is_static: false, is_eof: false, @@ -67,7 +69,7 @@ impl CallInputs { /// Creates new boxed call inputs. /// /// Returns `None` if the transaction is not a call. - pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { + pub fn new_boxed(tx_env: &impl Transaction, gas_limit: u64) -> Option> { Self::new(tx_env, gas_limit).map(Box::new) } diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index adae96ac2d..cafd2caa07 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -1,5 +1,7 @@ +use revm_primitives::Transaction; + pub use crate::primitives::CreateScheme; -use crate::primitives::{Address, Bytes, TxEnv, TxKind, U256}; +use crate::primitives::{Address, Bytes, TxKind, U256}; use std::boxed::Box; /// Inputs for a create call. @@ -20,22 +22,22 @@ pub struct CreateInputs { impl CreateInputs { /// Creates new create inputs. - pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { - let TxKind::Create = tx_env.transact_to else { + pub fn new(tx_env: &impl Transaction, gas_limit: u64) -> Option { + let TxKind::Create = tx_env.transact_to() else { return None; }; Some(CreateInputs { - caller: tx_env.caller, + caller: *tx_env.caller(), scheme: CreateScheme::Create, - value: tx_env.value, - init_code: tx_env.data.clone(), + value: *tx_env.value(), + init_code: tx_env.data().clone(), gas_limit, }) } /// Returns boxed create inputs. - pub fn new_boxed(tx_env: &TxEnv, gas_limit: u64) -> Option> { + pub fn new_boxed(tx_env: &impl Transaction, gas_limit: u64) -> Option> { Self::new(tx_env, gas_limit).map(Box::new) } diff --git a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs index 30bc525a4e..fd8b63f1dd 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs @@ -1,4 +1,6 @@ -use crate::primitives::{Address, Bytes, Eof, TxEnv, U256}; +use revm_primitives::ChainSpec; + +use crate::primitives::{Address, Bytes, Eof, Transaction as _, U256}; /// EOF create can be called from two places: /// * EOFCREATE opcode @@ -73,13 +75,13 @@ impl EOFCreateInputs { } /// Creates new EOFCreateInputs from transaction. - pub fn new_tx(tx: &TxEnv, gas_limit: u64) -> Self { + pub fn new_tx(tx: &ChainSpecT::Transaction, gas_limit: u64) -> Self { EOFCreateInputs::new( - tx.caller, - tx.value, + *tx.caller(), + *tx.value(), gas_limit, EOFCreateKind::Tx { - initdata: tx.data.clone(), + initdata: tx.data().clone(), }, ) } diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index 5617a0d73c..a07f4ae6e7 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -427,32 +427,32 @@ macro_rules! opcodes { opcodes! { 0x00 => STOP => control::stop => stack_io(0, 0), terminating; - 0x01 => ADD => arithmetic::add => stack_io(2, 1); - 0x02 => MUL => arithmetic::mul => stack_io(2, 1); - 0x03 => SUB => arithmetic::sub => stack_io(2, 1); - 0x04 => DIV => arithmetic::div => stack_io(2, 1); - 0x05 => SDIV => arithmetic::sdiv => stack_io(2, 1); - 0x06 => MOD => arithmetic::rem => stack_io(2, 1); - 0x07 => SMOD => arithmetic::smod => stack_io(2, 1); - 0x08 => ADDMOD => arithmetic::addmod => stack_io(3, 1); - 0x09 => MULMOD => arithmetic::mulmod => stack_io(3, 1); + 0x01 => ADD => arithmetic::add => stack_io(2, 1); + 0x02 => MUL => arithmetic::mul => stack_io(2, 1); + 0x03 => SUB => arithmetic::sub => stack_io(2, 1); + 0x04 => DIV => arithmetic::div => stack_io(2, 1); + 0x05 => SDIV => arithmetic::sdiv => stack_io(2, 1); + 0x06 => MOD => arithmetic::rem => stack_io(2, 1); + 0x07 => SMOD => arithmetic::smod => stack_io(2, 1); + 0x08 => ADDMOD => arithmetic::addmod => stack_io(3, 1); + 0x09 => MULMOD => arithmetic::mulmod => stack_io(3, 1); 0x0A => EXP => arithmetic::exp:: => stack_io(2, 1); - 0x0B => SIGNEXTEND => arithmetic::signextend => stack_io(2, 1); + 0x0B => SIGNEXTEND => arithmetic::signextend => stack_io(2, 1); // 0x0C // 0x0D // 0x0E // 0x0F - 0x10 => LT => bitwise::lt => stack_io(2, 1); - 0x11 => GT => bitwise::gt => stack_io(2, 1); - 0x12 => SLT => bitwise::slt => stack_io(2, 1); - 0x13 => SGT => bitwise::sgt => stack_io(2, 1); - 0x14 => EQ => bitwise::eq => stack_io(2, 1); - 0x15 => ISZERO => bitwise::iszero => stack_io(1, 1); - 0x16 => AND => bitwise::bitand => stack_io(2, 1); - 0x17 => OR => bitwise::bitor => stack_io(2, 1); - 0x18 => XOR => bitwise::bitxor => stack_io(2, 1); - 0x19 => NOT => bitwise::not => stack_io(1, 1); - 0x1A => BYTE => bitwise::byte => stack_io(2, 1); + 0x10 => LT => bitwise::lt => stack_io(2, 1); + 0x11 => GT => bitwise::gt => stack_io(2, 1); + 0x12 => SLT => bitwise::slt => stack_io(2, 1); + 0x13 => SGT => bitwise::sgt => stack_io(2, 1); + 0x14 => EQ => bitwise::eq => stack_io(2, 1); + 0x15 => ISZERO => bitwise::iszero => stack_io(1, 1); + 0x16 => AND => bitwise::bitand => stack_io(2, 1); + 0x17 => OR => bitwise::bitor => stack_io(2, 1); + 0x18 => XOR => bitwise::bitxor => stack_io(2, 1); + 0x19 => NOT => bitwise::not => stack_io(1, 1); + 0x1A => BYTE => bitwise::byte => stack_io(2, 1); 0x1B => SHL => bitwise::shl:: => stack_io(2, 1); 0x1C => SHR => bitwise::shr:: => stack_io(2, 1); 0x1D => SAR => bitwise::sar:: => stack_io(2, 1); @@ -474,24 +474,24 @@ opcodes! { // 0x2D // 0x2E // 0x2F - 0x30 => ADDRESS => system::address => stack_io(0, 1); + 0x30 => ADDRESS => system::address => stack_io(0, 1); 0x31 => BALANCE => host::balance:: => stack_io(1, 1); - 0x32 => ORIGIN => host_env::origin => stack_io(0, 1); - 0x33 => CALLER => system::caller => stack_io(0, 1); - 0x34 => CALLVALUE => system::callvalue => stack_io(0, 1); - 0x35 => CALLDATALOAD => system::calldataload => stack_io(1, 1); - 0x36 => CALLDATASIZE => system::calldatasize => stack_io(0, 1); - 0x37 => CALLDATACOPY => system::calldatacopy => stack_io(3, 0); - 0x38 => CODESIZE => system::codesize => stack_io(0, 1), not_eof; - 0x39 => CODECOPY => system::codecopy => stack_io(3, 0), not_eof; - - 0x3A => GASPRICE => host_env::gasprice => stack_io(0, 1); + 0x32 => ORIGIN => host_env::origin => stack_io(0, 1); + 0x33 => CALLER => system::caller => stack_io(0, 1); + 0x34 => CALLVALUE => system::callvalue => stack_io(0, 1); + 0x35 => CALLDATALOAD => system::calldataload => stack_io(1, 1); + 0x36 => CALLDATASIZE => system::calldatasize => stack_io(0, 1); + 0x37 => CALLDATACOPY => system::calldatacopy => stack_io(3, 0); + 0x38 => CODESIZE => system::codesize => stack_io(0, 1), not_eof; + 0x39 => CODECOPY => system::codecopy => stack_io(3, 0), not_eof; + + 0x3A => GASPRICE => host_env::gasprice => stack_io(0, 1); 0x3B => EXTCODESIZE => host::extcodesize:: => stack_io(1, 1), not_eof; 0x3C => EXTCODECOPY => host::extcodecopy:: => stack_io(4, 0), not_eof; 0x3D => RETURNDATASIZE => system::returndatasize:: => stack_io(0, 1); 0x3E => RETURNDATACOPY => system::returndatacopy:: => stack_io(3, 0); 0x3F => EXTCODEHASH => host::extcodehash:: => stack_io(1, 1), not_eof; - 0x40 => BLOCKHASH => host::blockhash:: => stack_io(1, 1); + 0x40 => BLOCKHASH => host::blockhash:: => stack_io(1, 1); 0x41 => COINBASE => host_env::coinbase => stack_io(0, 1); 0x42 => TIMESTAMP => host_env::timestamp => stack_io(0, 1); 0x43 => NUMBER => host_env::block_number => stack_io(0, 1); @@ -507,10 +507,10 @@ opcodes! { // 0x4D // 0x4E // 0x4F - 0x50 => POP => stack::pop => stack_io(1, 0); - 0x51 => MLOAD => memory::mload => stack_io(1, 1); - 0x52 => MSTORE => memory::mstore => stack_io(2, 0); - 0x53 => MSTORE8 => memory::mstore8 => stack_io(2, 0); + 0x50 => POP => stack::pop => stack_io(1, 0); + 0x51 => MLOAD => memory::mload => stack_io(1, 1); + 0x52 => MSTORE => memory::mstore => stack_io(2, 0); + 0x53 => MSTORE8 => memory::mstore8 => stack_io(2, 0); 0x54 => SLOAD => host::sload:: => stack_io(1, 1); 0x55 => SSTORE => host::sstore:: => stack_io(2, 0); 0x56 => JUMP => control::jump => stack_io(1, 0), not_eof; @@ -674,7 +674,7 @@ opcodes! { 0xF0 => CREATE => contract::create:: => stack_io(3, 1), not_eof; 0xF1 => CALL => contract::call:: => stack_io(7, 1), not_eof; 0xF2 => CALLCODE => contract::call_code:: => stack_io(7, 1), not_eof; - 0xF3 => RETURN => control::ret => stack_io(2, 0), terminating; + 0xF3 => RETURN => control::ret => stack_io(2, 0), terminating; 0xF4 => DELEGATECALL => contract::delegate_call:: => stack_io(6, 1), not_eof; 0xF5 => CREATE2 => contract::create:: => stack_io(4, 1), not_eof; // 0xF6 @@ -685,7 +685,7 @@ opcodes! { 0xFB => EXTSTATICCALL => contract::extstaticcall => stack_io(3, 1); // 0xFC 0xFD => REVERT => control::revert:: => stack_io(2, 0), terminating; - 0xFE => INVALID => control::invalid => stack_io(0, 0), terminating; + 0xFE => INVALID => control::invalid => stack_io(0, 0), terminating; 0xFF => SELFDESTRUCT => host::selfdestruct:: => stack_io(1, 0), not_eof, terminating; } diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 626f2d4405..417590f9a8 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -87,14 +87,6 @@ hashbrown = ["revm-primitives/hashbrown"] asm-keccak = ["revm-primitives/asm-keccak"] optimism = ["revm-primitives/optimism", "secp256r1"] -# Optimism default handler enabled Optimism handler register by default in EvmBuilder. -optimism-default-handler = [ - "optimism", - "revm-primitives/optimism-default-handler", -] -negate-optimism-default-handler = [ - "revm-primitives/negate-optimism-default-handler", -] # Enables the p256verify precompile. secp256r1 = ["dep:p256"] diff --git a/crates/precompile/benches/bench.rs b/crates/precompile/benches/bench.rs index faae103a95..366b6331a2 100644 --- a/crates/precompile/benches/bench.rs +++ b/crates/precompile/benches/bench.rs @@ -9,7 +9,7 @@ use revm_precompile::{ secp256k1::ec_recover_run, Bytes, }; -use revm_primitives::{hex, keccak256, Env, U256, VERSIONED_HASH_VERSION_KZG}; +use revm_primitives::{hex, keccak256, CfgEnv, U256, VERSIONED_HASH_VERSION_KZG}; use secp256k1::{Message, SecretKey, SECP256K1}; use sha2::{Digest, Sha256}; @@ -106,7 +106,7 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { let kzg_input = [versioned_hash, z, y, commitment, proof].concat().into(); let gas = 50000; - let env = Env::default(); + let env = CfgEnv::default(); let output = run(&kzg_input, gas, &env).unwrap(); println!("gas used by kzg precompile: {:?}", output.gas_used); diff --git a/crates/precompile/src/fatal_precompile.rs b/crates/precompile/src/fatal_precompile.rs index 4dfaee8db3..8a01cd58a1 100644 --- a/crates/precompile/src/fatal_precompile.rs +++ b/crates/precompile/src/fatal_precompile.rs @@ -1,5 +1,5 @@ use crate::primitives::{ - Address, Bytes, Env, Precompile, PrecompileErrors, PrecompileResult, StatefulPrecompile, + Address, Bytes, CfgEnv, Precompile, PrecompileErrors, PrecompileResult, StatefulPrecompile, }; use crate::PrecompileWithAddress; use std::{string::String, sync::Arc}; @@ -27,7 +27,7 @@ impl FatalPrecompile { } impl StatefulPrecompile for FatalPrecompile { - fn call(&self, _: &Bytes, _: u64, _: &Env) -> PrecompileResult { + fn call(&self, _: &Bytes, _: u64, _: &CfgEnv) -> PrecompileResult { Err(PrecompileErrors::Fatal { msg: self.msg.clone(), }) diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index 6f295219a6..98c4fe10d3 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -6,7 +6,7 @@ cfg_if::cfg_if! { use kzg_rs::{Bytes32, Bytes48, KzgProof, KzgSettings}; } } -use revm_primitives::{hex_literal::hex, Bytes, Env, PrecompileOutput}; +use revm_primitives::{hex_literal::hex, Bytes, CfgEnv, PrecompileOutput}; use sha2::{Digest, Sha256}; pub const POINT_EVALUATION: PrecompileWithAddress = @@ -30,7 +30,7 @@ pub const RETURN_VALUE: &[u8; 64] = &hex!( /// | versioned_hash | z | y | commitment | proof | /// | 32 | 32 | 32 | 48 | 48 | /// with z and y being padded 32 byte big endian values -pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { +pub fn run(input: &Bytes, gas_limit: u64, cfg: &CfgEnv) -> PrecompileResult { if gas_limit < GAS_COST { return Err(Error::OutOfGas.into()); } @@ -52,7 +52,7 @@ pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { let z = as_bytes32(&input[32..64]); let y = as_bytes32(&input[64..96]); let proof = as_bytes48(&input[144..192]); - if !verify_kzg_proof(commitment, z, y, proof, env.cfg.kzg_settings.get()) { + if !verify_kzg_proof(commitment, z, y, proof, cfg.kzg_settings.get()) { return Err(Error::BlobVerifyKzgProofFailed.into()); } @@ -118,7 +118,7 @@ mod tests { let expected_output = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); let gas = 50000; - let env = Env::default(); + let env = CfgEnv::default(); let output = run(&input.into(), gas, &env).unwrap(); assert_eq!(output.gas_used, gas); assert_eq!(output.bytes[..], expected_output); diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 662dca6a21..14a605ef1d 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -294,10 +294,6 @@ impl PrecompileSpecId { CANCUN => Self::CANCUN, PRAGUE | PRAGUE_EOF => Self::PRAGUE, LATEST => Self::LATEST, - #[cfg(feature = "optimism")] - BEDROCK | REGOLITH | CANYON => Self::BERLIN, - #[cfg(feature = "optimism")] - ECOTONE | FJORD => Self::CANCUN, } } } diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 1be794b95c..d99c0a835a 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -87,9 +87,6 @@ asm-keccak = ["alloy-primitives/asm-keccak"] portable = ["c-kzg?/portable"] optimism = [] -# Optimism default handler enabled Optimism handler register by default in EvmBuilder. -optimism-default-handler = ["optimism"] -negate-optimism-default-handler = [] dev = [ "memory_limit", diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs new file mode 100644 index 0000000000..ac08ac24b4 --- /dev/null +++ b/crates/primitives/src/block.rs @@ -0,0 +1,67 @@ +use crate::{Address, BlobExcessGasAndPrice, B256, U256}; +use core::fmt::Debug; + +/// Trait for retrieving block information required for execution. +pub trait Block: Clone + Debug + Default + PartialEq + Eq { + /// The number of ancestor blocks of this block (block height). + fn number(&self) -> &U256; + + /// Coinbase or miner or address that created and signed the block. + /// + /// This is the receiver address of all the gas spent in the block. + fn coinbase(&self) -> &Address; + + /// The timestamp of the block in seconds since the UNIX epoch. + fn timestamp(&self) -> &U256; + + /// The gas limit of the block. + fn gas_limit(&self) -> &U256; + + /// The base fee per gas, added in the London upgrade with [EIP-1559]. + /// + /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + fn basefee(&self) -> &U256; + + /// The difficulty of the block. + /// + /// Unused after the Paris (AKA the merge) upgrade, and replaced by `prevrandao`. + fn difficulty(&self) -> &U256; + + /// The output of the randomness beacon provided by the beacon chain. + /// + /// Replaces `difficulty` after the Paris (AKA the merge) upgrade with [EIP-4399]. + /// + /// NOTE: `prevrandao` can be found in a block in place of `mix_hash`. + /// + /// [EIP-4399]: https://eips.ethereum.org/EIPS/eip-4399 + fn prevrandao(&self) -> Option<&B256>; + + /// Excess blob gas and blob gasprice. + /// See also [`crate::calc_excess_blob_gas`] + /// and [`crate::calc_blob_gasprice`]. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + fn blob_excess_gas_and_price(&self) -> Option<&BlobExcessGasAndPrice>; +} + +/// See [EIP-4844] and [`crate::calc_blob_gasprice`]. +/// +/// Returns `None` if `Cancun` is not enabled. This is enforced in [`crate::Env::validate_block_env`]. +/// +/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 +#[inline] +pub fn get_blob_gasprice(block: &impl Block) -> Option<&u128> { + block.blob_excess_gas_and_price().map(|a| &a.blob_gasprice) +} + +/// Return `blob_excess_gas` header field. See [EIP-4844]. +/// +/// Returns `None` if `Cancun` is not enabled. This is enforced in [`crate::Env::validate_block_env`]. +/// +/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 +#[inline] +pub fn get_blob_excess_gas(block: &impl Block) -> Option { + block.blob_excess_gas_and_price().map(|a| a.excess_blob_gas) +} diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs new file mode 100644 index 0000000000..fe4b6d508b --- /dev/null +++ b/crates/primitives/src/chain_spec.rs @@ -0,0 +1,57 @@ +use cfg_if::cfg_if; + +use crate::{Block, SpecId, Transaction}; + +use core::{fmt::Debug, hash::Hash}; + +/// The type that enumerates the chain's hardforks. +pub trait HardforkTrait: Clone + Copy + Default + PartialEq + Eq + Into {} + +impl HardforkTrait for HardforkT where + HardforkT: Clone + Copy + Default + PartialEq + Eq + Into +{ +} + +cfg_if! { + if #[cfg(feature = "serde")] { + /// The type that enumerates chain-specific halt reasons. + pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + Hash + From + serde::de::DeserializeOwned + serde::Serialize {} + + impl HaltReasonTrait for HaltReasonT where + HaltReasonT: Clone + Debug + PartialEq + Eq + Hash + From + serde::de::DeserializeOwned + serde::Serialize + { + } + } else { + /// The type that enumerates chain-specific halt reasons. + pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + Hash + From {} + + impl HaltReasonTrait for HaltReasonT where + HaltReasonT: Clone + Debug + PartialEq + Eq + Hash + From + { + } + } +} + +pub trait ChainSpec: Clone + Debug + Default + Sized + 'static { + /// The type that contains all block information. + type Block: Block; + + /// The type that contains all transaction information. + type Transaction: Transaction; + + /// The type that enumerates the chain's hardforks. + type Hardfork: HardforkTrait; + + /// Halt reason type. + type HaltReason: HaltReasonTrait; +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct EthChainSpec; + +impl ChainSpec for EthChainSpec { + type Block = crate::BlockEnv; + type Hardfork = SpecId; + type HaltReason = crate::HaltReason; + type Transaction = crate::TxEnv; +} diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 98b70ec18f..9ab9e57d9c 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,15 +1,13 @@ pub mod eip7702; -pub mod handler_cfg; pub use eip7702::{ Authorization, AuthorizationList, RecoveredAuthorization, Signature, SignedAuthorization, }; -pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg}; use crate::{ - calc_blob_gasprice, AccessListItem, Account, Address, Bytes, InvalidHeader, InvalidTransaction, - Spec, SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, - MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, + block, calc_blob_gasprice, transaction, AccessListItem, Account, Address, Block, Bytes, + ChainSpec, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, B256, KECCAK_EMPTY, + MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, }; use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; @@ -20,16 +18,16 @@ use std::vec::Vec; /// EVM environment configuration. #[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Env { +pub struct Env { /// Configuration of the EVM itself. pub cfg: CfgEnv, /// Configuration of the block the transaction is in. - pub block: BlockEnv, + pub block: ChainSpecT::Block, /// Configuration of the transaction that is being executed. - pub tx: TxEnv, + pub tx: ChainSpecT::Transaction, } -impl Env { +impl Env { /// Resets environment to default values. #[inline] pub fn clear(&mut self) { @@ -38,17 +36,18 @@ impl Env { /// Create boxed [Env]. #[inline] - pub fn boxed(cfg: CfgEnv, block: BlockEnv, tx: TxEnv) -> Box { + pub fn boxed(cfg: CfgEnv, block: ChainSpecT::Block, tx: ChainSpecT::Transaction) -> Box { Box::new(Self { cfg, block, tx }) } /// Calculates the effective gas price of the transaction. #[inline] pub fn effective_gas_price(&self) -> U256 { - if let Some(priority_fee) = self.tx.gas_priority_fee { - min(self.tx.gas_price, self.block.basefee + priority_fee) + let gas_price = self.tx.gas_price(); + if let Some(priority_fee) = self.tx.gas_priority_fee() { + min(*gas_price, self.block.basefee() + priority_fee) } else { - self.tx.gas_price + *gas_price } } @@ -59,8 +58,9 @@ impl Env { /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 #[inline] pub fn calc_data_fee(&self) -> Option { - self.block.get_blob_gasprice().map(|blob_gas_price| { - U256::from(blob_gas_price).saturating_mul(U256::from(self.tx.get_total_blob_gas())) + block::get_blob_gasprice(&self.block).map(|blob_gas_price| { + U256::from(*blob_gas_price) + .saturating_mul(U256::from(transaction::get_total_blob_gas(&self.tx))) }) } @@ -72,8 +72,9 @@ impl Env { /// See EIP-4844: /// pub fn calc_max_data_fee(&self) -> Option { - self.tx.max_fee_per_blob_gas.map(|max_fee_per_blob_gas| { - max_fee_per_blob_gas.saturating_mul(U256::from(self.tx.get_total_blob_gas())) + self.tx.max_fee_per_blob_gas().map(|max_fee_per_blob_gas| { + max_fee_per_blob_gas + .saturating_mul(U256::from(transaction::get_total_blob_gas(&self.tx))) }) } @@ -81,11 +82,11 @@ impl Env { #[inline] pub fn validate_block_env(&self) -> Result<(), InvalidHeader> { // `prevrandao` is required for the merge - if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao.is_none() { + if SPEC::enabled(SpecId::MERGE) && self.block.prevrandao().is_none() { return Err(InvalidHeader::PrevrandaoNotSet); } // `excess_blob_gas` is required for Cancun - if SPEC::enabled(SpecId::CANCUN) && self.block.blob_excess_gas_and_price.is_none() { + if SPEC::enabled(SpecId::CANCUN) && self.block.blob_excess_gas_and_price().is_none() { return Err(InvalidHeader::ExcessBlobGasNotSet); } Ok(()) @@ -97,7 +98,7 @@ impl Env { #[inline] pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { // Check if the transaction's chain id is correct - if let Some(tx_chain_id) = self.tx.chain_id { + if let Some(tx_chain_id) = self.tx.chain_id() { if tx_chain_id != self.cfg.chain_id { return Err(InvalidTransaction::InvalidChainId); } @@ -105,20 +106,20 @@ impl Env { // Check if gas_limit is more than block_gas_limit if !self.cfg.is_block_gas_limit_disabled() - && U256::from(self.tx.gas_limit) > self.block.gas_limit + && U256::from(self.tx.gas_limit()) > *self.block.gas_limit() { return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); } // Check that access list is empty for transactions before BERLIN - if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list.is_empty() { + if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list().is_empty() { return Err(InvalidTransaction::AccessListNotSupported); } // BASEFEE tx check if SPEC::enabled(SpecId::LONDON) { - if let Some(priority_fee) = self.tx.gas_priority_fee { - if priority_fee > self.tx.gas_price { + if let Some(priority_fee) = self.tx.gas_priority_fee() { + if priority_fee > self.tx.gas_price() { // or gas_max_fee for eip1559 return Err(InvalidTransaction::PriorityFeeGreaterThanMaxFee); } @@ -126,41 +127,41 @@ impl Env { // check minimal cost against basefee if !self.cfg.is_base_fee_check_disabled() - && self.effective_gas_price() < self.block.basefee + && self.effective_gas_price() < *self.block.basefee() { return Err(InvalidTransaction::GasPriceLessThanBasefee); } } // EIP-3860: Limit and meter initcode - if SPEC::enabled(SpecId::SHANGHAI) && self.tx.transact_to.is_create() { + if SPEC::enabled(SpecId::SHANGHAI) && self.tx.transact_to().is_create() { let max_initcode_size = self .cfg .limit_contract_code_size .map(|limit| limit.saturating_mul(2)) .unwrap_or(MAX_INITCODE_SIZE); - if self.tx.data.len() > max_initcode_size { + if self.tx.data().len() > max_initcode_size { return Err(InvalidTransaction::CreateInitCodeSizeLimit); } } // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set if !SPEC::enabled(SpecId::CANCUN) - && (self.tx.max_fee_per_blob_gas.is_some() || !self.tx.blob_hashes.is_empty()) + && (self.tx.max_fee_per_blob_gas().is_some() || !self.tx.blob_hashes().is_empty()) { return Err(InvalidTransaction::BlobVersionedHashesNotSupported); } // Presence of max_fee_per_blob_gas means that this is blob transaction. - if let Some(max) = self.tx.max_fee_per_blob_gas { + if let Some(max) = self.tx.max_fee_per_blob_gas() { // ensure that the user was willing to at least pay the current blob gasprice - let price = self.block.get_blob_gasprice().expect("already checked"); - if U256::from(price) > max { + let price = block::get_blob_gasprice(&self.block).expect("already checked"); + if U256::from(*price) > *max { return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); } // there must be at least one blob - if self.tx.blob_hashes.is_empty() { + if self.tx.blob_hashes().is_empty() { return Err(InvalidTransaction::EmptyBlobs); } @@ -168,12 +169,12 @@ impl Env { // that it MUST NOT be nil and therefore must always represent // a 20-byte address. This means that blob transactions cannot // have the form of a create transaction. - if self.tx.transact_to.is_create() { + if self.tx.transact_to().is_create() { return Err(InvalidTransaction::BlobCreateTransaction); } // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG - for blob in self.tx.blob_hashes.iter() { + for blob in self.tx.blob_hashes() { if blob[0] != VERSIONED_HASH_VERSION_KZG { return Err(InvalidTransaction::BlobVersionNotSupported); } @@ -181,7 +182,7 @@ impl Env { // ensure the total blob gas spent is at most equal to the limit // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK - let num_blobs = self.tx.blob_hashes.len(); + let num_blobs = self.tx.blob_hashes().len(); if num_blobs > MAX_BLOB_NUMBER_PER_BLOCK as usize { return Err(InvalidTransaction::TooManyBlobs { have: num_blobs, @@ -190,19 +191,19 @@ impl Env { } } else { // if max_fee_per_blob_gas is not set, then blob_hashes must be empty - if !self.tx.blob_hashes.is_empty() { + if !self.tx.blob_hashes().is_empty() { return Err(InvalidTransaction::BlobVersionedHashesNotSupported); } } // check if EIP-7702 transaction is enabled. - if !SPEC::enabled(SpecId::PRAGUE) && self.tx.authorization_list.is_some() { + if !SPEC::enabled(SpecId::PRAGUE) && self.tx.authorization_list().is_some() { return Err(InvalidTransaction::AuthorizationListNotSupported); } - if self.tx.authorization_list.is_some() { + if self.tx.authorization_list().is_some() { // Check if other fields are unset. - if self.tx.max_fee_per_blob_gas.is_some() || !self.tx.blob_hashes.is_empty() { + if self.tx.max_fee_per_blob_gas().is_some() || !self.tx.blob_hashes().is_empty() { return Err(InvalidTransaction::AuthorizationListInvalidFields); } } @@ -224,7 +225,7 @@ impl Env { } // Check that the transaction's nonce is correct - if let Some(tx) = self.tx.nonce { + if let Some(tx) = self.tx.nonce() { let state = account.info.nonce; match tx.cmp(&state) { Ordering::Greater => { @@ -237,9 +238,9 @@ impl Env { } } - let mut balance_check = U256::from(self.tx.gas_limit) - .checked_mul(self.tx.gas_price) - .and_then(|gas_cost| gas_cost.checked_add(self.tx.value)) + let mut balance_check = U256::from(self.tx.gas_limit()) + .checked_mul(*self.tx.gas_price()) + .and_then(|gas_cost| gas_cost.checked_add(*self.tx.value())) .ok_or(InvalidTransaction::OverflowPaymentInTransaction)?; if SPEC::enabled(SpecId::CANCUN) { @@ -470,34 +471,47 @@ impl BlockEnv { pub fn set_blob_excess_gas_and_price(&mut self, excess_blob_gas: u64) { self.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas)); } - /// See [EIP-4844] and [`crate::calc_blob_gasprice`]. - /// - /// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 +} + +impl Block for BlockEnv { #[inline] - pub fn get_blob_gasprice(&self) -> Option { - self.blob_excess_gas_and_price - .as_ref() - .map(|a| a.blob_gasprice) + fn number(&self) -> &U256 { + &self.number } - /// Return `blob_excess_gas` header field. See [EIP-4844]. - /// - /// Returns `None` if `Cancun` is not enabled. This is enforced in [`Env::validate_block_env`]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 #[inline] - pub fn get_blob_excess_gas(&self) -> Option { - self.blob_excess_gas_and_price - .as_ref() - .map(|a| a.excess_blob_gas) + fn coinbase(&self) -> &Address { + &self.coinbase } - /// Clears environment and resets fields to default values. #[inline] - pub fn clear(&mut self) { - *self = Self::default(); + fn timestamp(&self) -> &U256 { + &self.timestamp + } + + #[inline] + fn gas_limit(&self) -> &U256 { + &self.gas_limit + } + + #[inline] + fn basefee(&self) -> &U256 { + &self.basefee + } + + #[inline] + fn difficulty(&self) -> &U256 { + &self.difficulty + } + + #[inline] + fn prevrandao(&self) -> Option<&B256> { + self.prevrandao.as_ref() + } + + #[inline] + fn blob_excess_gas_and_price(&self) -> Option<&BlobExcessGasAndPrice> { + self.blob_excess_gas_and_price.as_ref() } } @@ -581,36 +595,84 @@ pub struct TxEnv { /// /// [EIP-Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) pub authorization_list: Option, - - #[cfg_attr(feature = "serde", serde(flatten))] - #[cfg(feature = "optimism")] - /// Optimism fields. - pub optimism: OptimismFields, } -pub enum TxType { - Legacy, - Eip1559, - BlobTx, - EofCreate, -} +impl Transaction for TxEnv { + type TransactionValidationError = InvalidTransaction; -impl TxEnv { - /// See [EIP-4844], [`Env::calc_data_fee`], and [`Env::calc_max_data_fee`]. - /// - /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 #[inline] - pub fn get_total_blob_gas(&self) -> u64 { - GAS_PER_BLOB * self.blob_hashes.len() as u64 + fn caller(&self) -> &Address { + &self.caller } - /// Clears environment and resets fields to default values. #[inline] - pub fn clear(&mut self) { - *self = Self::default(); + fn gas_limit(&self) -> u64 { + self.gas_limit + } + + #[inline] + fn gas_price(&self) -> &U256 { + &self.gas_price + } + + #[inline] + fn transact_to(&self) -> &TransactTo { + &self.transact_to + } + + #[inline] + fn value(&self) -> &U256 { + &self.value + } + + #[inline] + fn data(&self) -> &Bytes { + &self.data + } + + #[inline] + fn nonce(&self) -> Option { + self.nonce + } + + #[inline] + fn chain_id(&self) -> Option { + self.chain_id + } + + #[inline] + fn access_list(&self) -> &[AccessListItem] { + &self.access_list + } + + #[inline] + fn gas_priority_fee(&self) -> Option<&U256> { + self.gas_priority_fee.as_ref() + } + + #[inline] + fn blob_hashes(&self) -> &[B256] { + &self.blob_hashes + } + + #[inline] + fn max_fee_per_blob_gas(&self) -> Option<&U256> { + self.max_fee_per_blob_gas.as_ref() + } + + #[inline] + fn authorization_list(&self) -> Option<&AuthorizationList> { + self.authorization_list.as_ref() } } +pub enum TxType { + Legacy, + Eip1559, + BlobTx, + EofCreate, +} + impl Default for TxEnv { fn default() -> Self { Self { @@ -627,8 +689,6 @@ impl Default for TxEnv { blob_hashes: Vec::new(), max_fee_per_blob_gas: None, authorization_list: None, - #[cfg(feature = "optimism")] - optimism: OptimismFields::default(), } } } @@ -658,40 +718,6 @@ impl BlobExcessGasAndPrice { } } -/// Additional [TxEnv] fields for optimism. -#[cfg(feature = "optimism")] -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct OptimismFields { - /// The source hash is used to make sure that deposit transactions do - /// not have identical hashes. - /// - /// L1 originated deposit transaction source hashes are computed using - /// the hash of the l1 block hash and the l1 log index. - /// L1 attributes deposit source hashes are computed with the l1 block - /// hash and the sequence number = l2 block number - l2 epoch start - /// block number. - /// - /// These two deposit transaction sources specify a domain in the outer - /// hash so there are no collisions. - pub source_hash: Option, - /// The amount to increase the balance of the `from` account as part of - /// a deposit transaction. This is unconditional and is applied to the - /// `from` account even if the deposit transaction fails since - /// the deposit is pre-paid on L1. - pub mint: Option, - /// Whether or not the transaction is a system transaction. - pub is_system_transaction: Option, - /// An enveloped EIP-2718 typed transaction. This is used - /// to compute the L1 tx cost using the L1 block info, as - /// opposed to requiring downstream apps to compute the cost - /// externally. - /// This field is optional to allow the [TxEnv] to be constructed - /// for non-optimism chains when the `optimism` feature is enabled, - /// but the [CfgEnv] `optimism` field is set to false. - pub enveloped_tx: Option, -} - /// Transaction destination pub type TransactTo = TxKind; @@ -721,11 +747,13 @@ pub enum AnalysisKind { #[cfg(test)] mod tests { + use crate::EthChainSpec; + use super::*; #[test] fn test_validate_tx_chain_id() { - let mut env = Env::default(); + let mut env = Env::::default(); env.tx.chain_id = Some(1); env.cfg.chain_id = 2; assert_eq!( @@ -736,7 +764,7 @@ mod tests { #[test] fn test_validate_tx_access_list() { - let mut env = Env::default(); + let mut env = Env::::default(); env.tx.access_list = vec![AccessListItem { address: Address::ZERO, storage_keys: vec![], diff --git a/crates/primitives/src/env/handler_cfg.rs b/crates/primitives/src/env/handler_cfg.rs deleted file mode 100644 index f57a3e8c99..0000000000 --- a/crates/primitives/src/env/handler_cfg.rs +++ /dev/null @@ -1,159 +0,0 @@ -use super::{BlockEnv, CfgEnv, Env, SpecId, TxEnv}; -use core::ops::{Deref, DerefMut}; -use std::boxed::Box; - -/// Handler configuration fields. It is used to configure the handler. -/// It contains specification id and the Optimism related field if -/// optimism feature is enabled. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub struct HandlerCfg { - /// Specification identification. - pub spec_id: SpecId, - /// Optimism related field, it will append the Optimism handle register to the EVM. - #[cfg(feature = "optimism")] - pub is_optimism: bool, -} - -impl Default for HandlerCfg { - fn default() -> Self { - Self::new(SpecId::default()) - } -} - -impl HandlerCfg { - /// Creates new `HandlerCfg` instance. - pub fn new(spec_id: SpecId) -> Self { - cfg_if::cfg_if! { - if #[cfg(all(feature = "optimism-default-handler", - not(feature = "negate-optimism-default-handler")))] { - let is_optimism = true; - } else if #[cfg(feature = "optimism")] { - let is_optimism = false; - } - } - Self { - spec_id, - #[cfg(feature = "optimism")] - is_optimism, - } - } - - /// Creates new `HandlerCfg` instance with the optimism feature. - #[cfg(feature = "optimism")] - pub fn new_with_optimism(spec_id: SpecId, is_optimism: bool) -> Self { - Self { - spec_id, - is_optimism, - } - } - - /// Returns `true` if the optimism feature is enabled and flag is set to `true`. - pub fn is_optimism(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optimism")] { - self.is_optimism - } else { - false - } - } - } -} - -/// Configuration environment with the chain spec id. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct CfgEnvWithHandlerCfg { - /// Configuration environment. - pub cfg_env: CfgEnv, - /// Handler configuration fields. - pub handler_cfg: HandlerCfg, -} - -impl CfgEnvWithHandlerCfg { - /// Returns new instance of `CfgEnvWithHandlerCfg` with the handler configuration. - pub fn new(cfg_env: CfgEnv, handler_cfg: HandlerCfg) -> Self { - Self { - cfg_env, - handler_cfg, - } - } - - /// Returns new `CfgEnvWithHandlerCfg` instance with the chain spec id. - /// - /// is_optimism will be set to default value depending on `optimism-default-handler` feature. - pub fn new_with_spec_id(cfg_env: CfgEnv, spec_id: SpecId) -> Self { - Self::new(cfg_env, HandlerCfg::new(spec_id)) - } - - /// Enables the optimism feature. - #[cfg(feature = "optimism")] - pub fn enable_optimism(&mut self) { - self.handler_cfg.is_optimism = true; - } -} - -impl DerefMut for CfgEnvWithHandlerCfg { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.cfg_env - } -} - -impl Deref for CfgEnvWithHandlerCfg { - type Target = CfgEnv; - - fn deref(&self) -> &Self::Target { - &self.cfg_env - } -} - -/// Evm environment with the chain spec id. -#[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct EnvWithHandlerCfg { - /// Evm enironment. - pub env: Box, - /// Handler configuration fields. - pub handler_cfg: HandlerCfg, -} - -impl EnvWithHandlerCfg { - /// Returns new `EnvWithHandlerCfg` instance. - pub fn new(env: Box, handler_cfg: HandlerCfg) -> Self { - Self { env, handler_cfg } - } - - /// Returns new `EnvWithHandlerCfg` instance with the chain spec id. - /// - /// is_optimism will be set to default value depending on `optimism-default-handler` feature. - pub fn new_with_spec_id(env: Box, spec_id: SpecId) -> Self { - Self::new(env, HandlerCfg::new(spec_id)) - } - - /// Takes `CfgEnvWithHandlerCfg` and returns new `EnvWithHandlerCfg` instance. - pub fn new_with_cfg_env(cfg: CfgEnvWithHandlerCfg, block: BlockEnv, tx: TxEnv) -> Self { - Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.handler_cfg) - } - - /// Returns the specification id. - pub const fn spec_id(&self) -> SpecId { - self.handler_cfg.spec_id - } - - /// Enables the optimism handle register. - #[cfg(feature = "optimism")] - pub fn enable_optimism(&mut self) { - self.handler_cfg.is_optimism = true; - } -} - -impl DerefMut for EnvWithHandlerCfg { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.env - } -} - -impl Deref for EnvWithHandlerCfg { - type Target = Env; - - fn deref(&self) -> &Self::Target { - &self.env - } -} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index e29efe9b12..681ac101dd 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -12,12 +12,15 @@ mod constants; pub mod db; pub mod env; +pub mod block; +mod chain_spec; #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg; pub mod precompile; pub mod result; pub mod specification; pub mod state; +pub mod transaction; pub mod utilities; pub use alloy_eips::eip2930::{AccessList, AccessListItem}; pub use alloy_primitives::{ @@ -26,6 +29,7 @@ pub use alloy_primitives::{ }; pub use bitvec; pub use bytecode::*; +pub use chain_spec::*; pub use constants::*; pub use env::*; @@ -38,12 +42,14 @@ cfg_if::cfg_if! { } } +pub use block::Block; #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub use kzg::{EnvKzgSettings, KzgSettings}; pub use precompile::*; pub use result::*; pub use specification::*; pub use state::*; +pub use transaction::Transaction; pub use utilities::*; #[cfg(all(feature = "c-kzg", feature = "kzg-rs"))] diff --git a/crates/primitives/src/precompile.rs b/crates/primitives/src/precompile.rs index 22a7839021..890e1b537e 100644 --- a/crates/primitives/src/precompile.rs +++ b/crates/primitives/src/precompile.rs @@ -1,5 +1,5 @@ -use crate::{Bytes, Env}; -use core::fmt::{self}; +use crate::{Bytes, CfgEnv}; +use core::fmt; use dyn_clone::DynClone; use std::{boxed::Box, string::String, sync::Arc}; @@ -25,18 +25,18 @@ impl PrecompileOutput { } pub type StandardPrecompileFn = fn(&Bytes, u64) -> PrecompileResult; -pub type EnvPrecompileFn = fn(&Bytes, u64, env: &Env) -> PrecompileResult; +pub type EnvPrecompileFn = fn(&Bytes, u64, env: &CfgEnv) -> PrecompileResult; /// Stateful precompile trait. It is used to create /// a arc precompile Precompile::Stateful. pub trait StatefulPrecompile: Sync + Send { - fn call(&self, bytes: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult; + fn call(&self, bytes: &Bytes, gas_limit: u64, env: &CfgEnv) -> PrecompileResult; } /// Mutable stateful precompile trait. It is used to create /// a boxed precompile in Precompile::StatefulMut. pub trait StatefulPrecompileMut: DynClone + Send + Sync { - fn call_mut(&mut self, bytes: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult; + fn call_mut(&mut self, bytes: &Bytes, gas_limit: u64, env: &CfgEnv) -> PrecompileResult; } dyn_clone::clone_trait_object!(StatefulPrecompileMut); @@ -52,13 +52,13 @@ pub type StatefulPrecompileBox = Box; pub enum Precompile { /// Standard simple precompile that takes input and gas limit. Standard(StandardPrecompileFn), - /// Similar to Standard but takes reference to environment. + /// Similar to Standard but takes reference to [`CfgEnv`]. Env(EnvPrecompileFn), /// Stateful precompile that is Arc over [`StatefulPrecompile`] trait. - /// It takes a reference to input, gas limit and environment. + /// It takes a reference to input, gas limit and [`CfgEnv`]. Stateful(StatefulPrecompileArc), /// Mutable stateful precompile that is Box over [`StatefulPrecompileMut`] trait. - /// It takes a reference to input, gas limit and environment. + /// It takes a reference to input, gas limit and [`CfgEnv`]. StatefulMut(StatefulPrecompileBox), } @@ -109,7 +109,7 @@ impl Precompile { } /// Call the precompile with the given input and gas limit and return the result. - pub fn call(&mut self, bytes: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { + pub fn call(&mut self, bytes: &Bytes, gas_limit: u64, env: &CfgEnv) -> PrecompileResult { match *self { Precompile::Standard(p) => p(bytes, gas_limit), Precompile::Env(p) => p(bytes, gas_limit, env), @@ -121,7 +121,7 @@ impl Precompile { /// Call the precompile with the given input and gas limit and return the result. /// /// Returns an error if the precompile is mutable. - pub fn call_ref(&self, bytes: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { + pub fn call_ref(&self, bytes: &Bytes, gas_limit: u64, env: &CfgEnv) -> PrecompileResult { match *self { Precompile::Standard(p) => p(bytes, gas_limit), Precompile::Env(p) => p(bytes, gas_limit, env), @@ -234,7 +234,7 @@ mod test { &mut self, _bytes: &Bytes, _gas_limit: u64, - _env: &Env, + _env: &CfgEnv, ) -> PrecompileResult { Err(PrecompileError::OutOfGas.into()) } @@ -243,7 +243,7 @@ mod test { let mut p = Precompile::new_stateful_mut(MyPrecompile::default()); match &mut p { Precompile::StatefulMut(p) => { - let _ = p.call_mut(&Bytes::new(), 0, &Env::default()); + let _ = p.call_mut(&Bytes::new(), 0, &CfgEnv::default()); } _ => panic!("not a state"), } diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 858078ec02..fddad74a8b 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,18 +1,20 @@ -use crate::{Address, Bytes, EvmState, Log, U256}; +use crate::{Address, Bytes, ChainSpec, EthChainSpec, EvmState, Log, Transaction, U256}; use core::fmt; use std::{boxed::Box, string::String, vec::Vec}; /// Result of EVM execution. -pub type EVMResult = EVMResultGeneric; +pub type EVMResult = + EVMResultGeneric, ChainSpecT, DBError>; /// Generic result of EVM execution. Used to represent error and generic output. -pub type EVMResultGeneric = core::result::Result>; +pub type EVMResultGeneric = + core::result::Result>; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ResultAndState { +pub struct ResultAndState { /// Status of execution - pub result: ExecutionResult, + pub result: ExecutionResult, /// State that got updated pub state: EvmState, } @@ -20,7 +22,7 @@ pub struct ResultAndState { /// Result of a transaction execution. #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum ExecutionResult { +pub enum ExecutionResult { /// Returned successfully Success { reason: SuccessReason, @@ -33,13 +35,13 @@ pub enum ExecutionResult { Revert { gas_used: u64, output: Bytes }, /// Reverted for various reasons and spend all gas. Halt { - reason: HaltReason, + reason: ChainSpecT::HaltReason, /// Halting will spend all the gas, and will be equal to gas_limit. gas_used: u64, }, } -impl ExecutionResult { +impl ExecutionResult { /// Returns if transaction execution is successful. /// 1 indicates success, 0 indicates revert. /// @@ -135,11 +137,11 @@ impl Output { } /// Main EVM error. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum EVMError { +pub enum EVMError { /// Transaction validation error. - Transaction(InvalidTransaction), + Transaction(::TransactionValidationError), /// Header validation error. Header(InvalidHeader), /// Database error. @@ -152,9 +154,9 @@ pub enum EVMError { Precompile(String), } -impl EVMError { +impl EVMError { /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged. - pub fn map_db_err(self, op: F) -> EVMError + pub fn map_db_err(self, op: F) -> EVMError where F: FnOnce(DBError) -> E, { @@ -169,7 +171,13 @@ impl EVMError { } #[cfg(feature = "std")] -impl std::error::Error for EVMError { +impl std::error::Error + for EVMError +where + ChainSpecT: ChainSpec, + ::TransactionValidationError: + std::error::Error + 'static, +{ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::Transaction(e) => Some(e), @@ -180,7 +188,7 @@ impl std::error::Error for EVMError fmt::Display for EVMError { +impl fmt::Display for EVMError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Transaction(e) => write!(f, "transaction validation error: {e}"), @@ -191,13 +199,13 @@ impl fmt::Display for EVMError { } } -impl From for EVMError { +impl From for EVMError { fn from(value: InvalidTransaction) -> Self { Self::Transaction(value) } } -impl From for EVMError { +impl From for EVMError { fn from(value: InvalidHeader) -> Self { Self::Header(value) } @@ -311,9 +319,6 @@ pub enum InvalidTransaction { AuthorizationListNotSupported, /// EIP-7702 transaction has invalid fields set. AuthorizationListInvalidFields, - /// Optimism-specific transaction validation error. - #[cfg(feature = "optimism")] - OptimismError(OptimismInvalidTransaction), } #[cfg(feature = "std")] @@ -393,8 +398,6 @@ impl fmt::Display for InvalidTransaction { Self::AuthorizationListInvalidFields => { write!(f, "authorization list tx has invalid fields") } - #[cfg(feature = "optimism")] - Self::OptimismError(op_error) => op_error.fmt(f), } } } @@ -467,10 +470,6 @@ pub enum HaltReason { EofAuxDataTooSmall, /// EOF Subroutine stack overflow EOFFunctionStackOverflow, - - /* Optimism errors */ - #[cfg(feature = "optimism")] - FailedDeposit, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index 7ab9f370a8..db141155dc 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -5,7 +5,6 @@ pub use SpecId::*; /// Specification IDs and their activation block. /// /// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(not(feature = "optimism"))] #[repr(u8)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -34,43 +33,6 @@ pub enum SpecId { LATEST = u8::MAX, } -/// Specification IDs and their activation block. -/// -/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(feature = "optimism")] -#[repr(u8)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum SpecId { - FRONTIER = 0, - FRONTIER_THAWING = 1, - HOMESTEAD = 2, - DAO_FORK = 3, - TANGERINE = 4, - SPURIOUS_DRAGON = 5, - BYZANTIUM = 6, - CONSTANTINOPLE = 7, - PETERSBURG = 8, - ISTANBUL = 9, - MUIR_GLACIER = 10, - BERLIN = 11, - LONDON = 12, - ARROW_GLACIER = 13, - GRAY_GLACIER = 14, - MERGE = 15, - BEDROCK = 16, - REGOLITH = 17, - SHANGHAI = 18, - CANYON = 19, - CANCUN = 20, - ECOTONE = 21, - FJORD = 22, - PRAGUE = 23, - PRAGUE_EOF = 24, - #[default] - LATEST = u8::MAX, -} - impl SpecId { /// Returns the `SpecId` for the given `u8`. #[inline] @@ -110,16 +72,6 @@ impl From<&str> for SpecId { "Cancun" => Self::CANCUN, "Prague" => Self::PRAGUE, "PragueEOF" => Self::PRAGUE_EOF, - #[cfg(feature = "optimism")] - "Bedrock" => SpecId::BEDROCK, - #[cfg(feature = "optimism")] - "Regolith" => SpecId::REGOLITH, - #[cfg(feature = "optimism")] - "Canyon" => SpecId::CANYON, - #[cfg(feature = "optimism")] - "Ecotone" => SpecId::ECOTONE, - #[cfg(feature = "optimism")] - "Fjord" => SpecId::FJORD, _ => Self::LATEST, } } @@ -148,16 +100,6 @@ impl From for &'static str { SpecId::CANCUN => "Cancun", SpecId::PRAGUE => "Prague", SpecId::PRAGUE_EOF => "PragueEOF", - #[cfg(feature = "optimism")] - SpecId::BEDROCK => "Bedrock", - #[cfg(feature = "optimism")] - SpecId::REGOLITH => "Regolith", - #[cfg(feature = "optimism")] - SpecId::CANYON => "Canyon", - #[cfg(feature = "optimism")] - SpecId::ECOTONE => "Ecotone", - #[cfg(feature = "optimism")] - SpecId::FJORD => "Fjord", SpecId::LATEST => "Latest", } } @@ -208,99 +150,15 @@ spec!(PRAGUE_EOF, PragueEofSpec); spec!(LATEST, LatestSpec); -// Optimism Hardforks -#[cfg(feature = "optimism")] -spec!(BEDROCK, BedrockSpec); -#[cfg(feature = "optimism")] -spec!(REGOLITH, RegolithSpec); -#[cfg(feature = "optimism")] -spec!(CANYON, CanyonSpec); -#[cfg(feature = "optimism")] -spec!(ECOTONE, EcotoneSpec); -#[cfg(feature = "optimism")] -spec!(FJORD, FjordSpec); - -#[cfg(not(feature = "optimism"))] -#[macro_export] -macro_rules! spec_to_generic { - ($spec_id:expr, $e:expr) => {{ - match $spec_id { - $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => { - use $crate::FrontierSpec as SPEC; - $e - } - $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => { - use $crate::HomesteadSpec as SPEC; - $e - } - $crate::SpecId::TANGERINE => { - use $crate::TangerineSpec as SPEC; - $e - } - $crate::SpecId::SPURIOUS_DRAGON => { - use $crate::SpuriousDragonSpec as SPEC; - $e - } - $crate::SpecId::BYZANTIUM => { - use $crate::ByzantiumSpec as SPEC; - $e - } - $crate::SpecId::PETERSBURG | $crate::SpecId::CONSTANTINOPLE => { - use $crate::PetersburgSpec as SPEC; - $e - } - $crate::SpecId::ISTANBUL | $crate::SpecId::MUIR_GLACIER => { - use $crate::IstanbulSpec as SPEC; - $e - } - $crate::SpecId::BERLIN => { - use $crate::BerlinSpec as SPEC; - $e - } - $crate::SpecId::LONDON - | $crate::SpecId::ARROW_GLACIER - | $crate::SpecId::GRAY_GLACIER => { - use $crate::LondonSpec as SPEC; - $e - } - $crate::SpecId::MERGE => { - use $crate::MergeSpec as SPEC; - $e - } - $crate::SpecId::SHANGHAI => { - use $crate::ShanghaiSpec as SPEC; - $e - } - $crate::SpecId::CANCUN => { - use $crate::CancunSpec as SPEC; - $e - } - $crate::SpecId::LATEST => { - use $crate::LatestSpec as SPEC; - $e - } - $crate::SpecId::PRAGUE => { - use $crate::PragueSpec as SPEC; - $e - } - $crate::SpecId::PRAGUE_EOF => { - use $crate::PragueEofSpec as SPEC; - $e - } - } - }}; -} - -#[cfg(feature = "optimism")] #[macro_export] macro_rules! spec_to_generic { ($spec_id:expr, $e:expr) => {{ match $spec_id { - $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => { + $crate::SpecId::FRONTIER | $crate::SpecId::FRONTIER_THAWING => { use $crate::FrontierSpec as SPEC; $e } - $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => { + $crate::SpecId::HOMESTEAD | $crate::SpecId::DAO_FORK => { use $crate::HomesteadSpec as SPEC; $e } @@ -358,26 +216,6 @@ macro_rules! spec_to_generic { use $crate::PragueEofSpec as SPEC; $e } - $crate::SpecId::BEDROCK => { - use $crate::BedrockSpec as SPEC; - $e - } - $crate::SpecId::REGOLITH => { - use $crate::RegolithSpec as SPEC; - $e - } - $crate::SpecId::CANYON => { - use $crate::CanyonSpec as SPEC; - $e - } - $crate::SpecId::ECOTONE => { - use $crate::EcotoneSpec as SPEC; - $e - } - $crate::SpecId::FJORD => { - use $crate::FjordSpec as SPEC; - $e - } } }}; } @@ -406,138 +244,9 @@ mod tests { spec_to_generic!(ARROW_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); spec_to_generic!(GRAY_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); spec_to_generic!(MERGE, assert_eq!(SPEC::SPEC_ID, MERGE)); - #[cfg(feature = "optimism")] - spec_to_generic!(BEDROCK, assert_eq!(SPEC::SPEC_ID, BEDROCK)); - #[cfg(feature = "optimism")] - spec_to_generic!(REGOLITH, assert_eq!(SPEC::SPEC_ID, REGOLITH)); - spec_to_generic!(SHANGHAI, assert_eq!(SPEC::SPEC_ID, SHANGHAI)); - #[cfg(feature = "optimism")] - spec_to_generic!(CANYON, assert_eq!(SPEC::SPEC_ID, CANYON)); spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN)); - #[cfg(feature = "optimism")] - spec_to_generic!(ECOTONE, assert_eq!(SPEC::SPEC_ID, ECOTONE)); - #[cfg(feature = "optimism")] - spec_to_generic!(FJORD, assert_eq!(SPEC::SPEC_ID, FJORD)); spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE)); spec_to_generic!(PRAGUE_EOF, assert_eq!(SPEC::SPEC_ID, PRAGUE_EOF)); spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); } } - -#[cfg(feature = "optimism")] -#[cfg(test)] -mod optimism_tests { - use super::*; - - #[test] - fn test_bedrock_post_merge_hardforks() { - assert!(BedrockSpec::enabled(SpecId::MERGE)); - assert!(!BedrockSpec::enabled(SpecId::SHANGHAI)); - assert!(!BedrockSpec::enabled(SpecId::CANCUN)); - assert!(!BedrockSpec::enabled(SpecId::LATEST)); - assert!(BedrockSpec::enabled(SpecId::BEDROCK)); - assert!(!BedrockSpec::enabled(SpecId::REGOLITH)); - } - - #[test] - fn test_regolith_post_merge_hardforks() { - assert!(RegolithSpec::enabled(SpecId::MERGE)); - assert!(!RegolithSpec::enabled(SpecId::SHANGHAI)); - assert!(!RegolithSpec::enabled(SpecId::CANCUN)); - assert!(!RegolithSpec::enabled(SpecId::LATEST)); - assert!(RegolithSpec::enabled(SpecId::BEDROCK)); - assert!(RegolithSpec::enabled(SpecId::REGOLITH)); - } - - #[test] - fn test_bedrock_post_merge_hardforks_spec_id() { - assert!(SpecId::enabled(SpecId::BEDROCK, SpecId::MERGE)); - assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::SHANGHAI)); - assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::CANCUN)); - assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::LATEST)); - assert!(SpecId::enabled(SpecId::BEDROCK, SpecId::BEDROCK)); - assert!(!SpecId::enabled(SpecId::BEDROCK, SpecId::REGOLITH)); - } - - #[test] - fn test_regolith_post_merge_hardforks_spec_id() { - assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::MERGE)); - assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::SHANGHAI)); - assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::CANCUN)); - assert!(!SpecId::enabled(SpecId::REGOLITH, SpecId::LATEST)); - assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::BEDROCK)); - assert!(SpecId::enabled(SpecId::REGOLITH, SpecId::REGOLITH)); - } - - #[test] - fn test_canyon_post_merge_hardforks() { - assert!(CanyonSpec::enabled(SpecId::MERGE)); - assert!(CanyonSpec::enabled(SpecId::SHANGHAI)); - assert!(!CanyonSpec::enabled(SpecId::CANCUN)); - assert!(!CanyonSpec::enabled(SpecId::LATEST)); - assert!(CanyonSpec::enabled(SpecId::BEDROCK)); - assert!(CanyonSpec::enabled(SpecId::REGOLITH)); - assert!(CanyonSpec::enabled(SpecId::CANYON)); - } - - #[test] - fn test_canyon_post_merge_hardforks_spec_id() { - assert!(SpecId::enabled(SpecId::CANYON, SpecId::MERGE)); - assert!(SpecId::enabled(SpecId::CANYON, SpecId::SHANGHAI)); - assert!(!SpecId::enabled(SpecId::CANYON, SpecId::CANCUN)); - assert!(!SpecId::enabled(SpecId::CANYON, SpecId::LATEST)); - assert!(SpecId::enabled(SpecId::CANYON, SpecId::BEDROCK)); - assert!(SpecId::enabled(SpecId::CANYON, SpecId::REGOLITH)); - assert!(SpecId::enabled(SpecId::CANYON, SpecId::CANYON)); - } - - #[test] - fn test_ecotone_post_merge_hardforks() { - assert!(EcotoneSpec::enabled(SpecId::MERGE)); - assert!(EcotoneSpec::enabled(SpecId::SHANGHAI)); - assert!(EcotoneSpec::enabled(SpecId::CANCUN)); - assert!(!EcotoneSpec::enabled(SpecId::LATEST)); - assert!(EcotoneSpec::enabled(SpecId::BEDROCK)); - assert!(EcotoneSpec::enabled(SpecId::REGOLITH)); - assert!(EcotoneSpec::enabled(SpecId::CANYON)); - assert!(EcotoneSpec::enabled(SpecId::ECOTONE)); - } - - #[test] - fn test_ecotone_post_merge_hardforks_spec_id() { - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::MERGE)); - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::SHANGHAI)); - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANCUN)); - assert!(!SpecId::enabled(SpecId::ECOTONE, SpecId::LATEST)); - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::BEDROCK)); - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::REGOLITH)); - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANYON)); - assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::ECOTONE)); - } - - #[test] - fn test_fjord_post_merge_hardforks() { - assert!(FjordSpec::enabled(SpecId::MERGE)); - assert!(FjordSpec::enabled(SpecId::SHANGHAI)); - assert!(FjordSpec::enabled(SpecId::CANCUN)); - assert!(!FjordSpec::enabled(SpecId::LATEST)); - assert!(FjordSpec::enabled(SpecId::BEDROCK)); - assert!(FjordSpec::enabled(SpecId::REGOLITH)); - assert!(FjordSpec::enabled(SpecId::CANYON)); - assert!(FjordSpec::enabled(SpecId::ECOTONE)); - assert!(FjordSpec::enabled(SpecId::FJORD)); - } - - #[test] - fn test_fjord_post_merge_hardforks_spec_id() { - assert!(SpecId::enabled(SpecId::FJORD, SpecId::MERGE)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::SHANGHAI)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::CANCUN)); - assert!(!SpecId::enabled(SpecId::FJORD, SpecId::LATEST)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::BEDROCK)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::REGOLITH)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::CANYON)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::ECOTONE)); - assert!(SpecId::enabled(SpecId::FJORD, SpecId::FJORD)); - } -} diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs new file mode 100644 index 0000000000..b0523cc5a8 --- /dev/null +++ b/crates/primitives/src/transaction.rs @@ -0,0 +1,82 @@ +use crate::{ + AccessListItem, Address, AuthorizationList, Bytes, InvalidTransaction, TxKind, B256, + GAS_PER_BLOB, U256, +}; +use cfg_if::cfg_if; +use core::fmt::{Debug, Display}; + +/// Trait for retrieving transaction information required for execution. +pub trait Transaction: Clone + Debug + Default + PartialEq + Eq { + cfg_if! { + if #[cfg(feature = "serde")] { + /// The error type that can be returned when validating a transaction. + type TransactionValidationError: Clone + Debug + Display + PartialEq + Eq + serde::de::DeserializeOwned + serde::Serialize + From; + } else { + /// The error type that can be returned when validating a transaction. + type TransactionValidationError: Clone + Debug + Display + PartialEq + Eq + From; + } + } + + /// Caller aka Author aka transaction signer. + fn caller(&self) -> &Address; + /// The gas limit of the transaction. + fn gas_limit(&self) -> u64; + /// The gas price of the transaction. + fn gas_price(&self) -> &U256; + /// The destination of the transaction. + fn transact_to(&self) -> &TxKind; + /// The value sent to `transact_to`. + fn value(&self) -> &U256; + /// The data of the transaction. + fn data(&self) -> &Bytes; + /// The nonce of the transaction. + /// + /// Caution: If set to `None`, then nonce validation against the account's nonce is skipped: [InvalidTransaction::NonceTooHigh] and [InvalidTransaction::NonceTooLow] + fn nonce(&self) -> Option; + /// The chain ID of the transaction. If set to `None`, no checks are performed. + /// + /// Incorporated as part of the Spurious Dragon upgrade via [EIP-155]. + /// + /// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155 + fn chain_id(&self) -> Option; + /// A list of addresses and storage keys that the transaction plans to access. + /// + /// Added in [EIP-2930]. + /// + /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 + fn access_list(&self) -> &[AccessListItem]; + /// The priority fee per gas. + /// + /// Incorporated as part of the London upgrade via [EIP-1559]. + /// + /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 + fn gas_priority_fee(&self) -> Option<&U256>; + /// The list of blob versioned hashes. Per EIP there should be at least + /// one blob present if [`Self::max_fee_per_blob_gas`] is `Some`. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + fn blob_hashes(&self) -> &[B256]; + /// The max fee per blob gas. + /// + /// Incorporated as part of the Cancun upgrade via [EIP-4844]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + fn max_fee_per_blob_gas(&self) -> Option<&U256>; + /// List of authorizations, that contains the signature that authorizes this + /// caller to place the code to signer account. + /// + /// Set EOA account code for one transaction + /// + /// [EIP-Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) + fn authorization_list(&self) -> Option<&AuthorizationList>; +} + +/// See [EIP-4844], [`crate::Env::calc_data_fee`], and [`crate::Env::calc_max_data_fee`]. +/// +/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 +#[inline] +pub fn get_total_blob_gas(transaction: &impl Transaction) -> u64 { + GAS_PER_BLOB * transaction.blob_hashes().len() as u64 +} diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 3e83415426..fbe8e3601f 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -28,8 +28,8 @@ revm-precompile = { path = "../precompile", version = "9.2.0", default-features # misc auto_impl = { version = "1.2", default-features = false } -cfg-if = "1.0" dyn-clone = "1.0" +enumn = { version = "0.1", optional = true } # Optional serde = { version = "1.0", default-features = false, features = [ @@ -84,17 +84,7 @@ portable = ["revm-precompile/portable", "revm-interpreter/portable"] test-utils = [] -optimism = ["revm-interpreter/optimism", "revm-precompile/optimism"] -# Optimism default handler enabled Optimism handler register by default in EvmBuilder. -optimism-default-handler = [ - "optimism", - "revm-precompile/optimism-default-handler", - "revm-interpreter/optimism-default-handler", -] -negate-optimism-default-handler = [ - "revm-precompile/negate-optimism-default-handler", - "revm-interpreter/negate-optimism-default-handler", -] +optimism = ["dep:enumn", "revm-interpreter/optimism", "revm-precompile/optimism"] ethersdb = ["std", "dep:tokio", "dep:ethers-providers", "dep:ethers-core"] diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index a135a367d2..bdba5206c0 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -4,7 +4,7 @@ use criterion::{ use revm::{ db::BenchmarkDB, interpreter::{analysis::to_analysed, Contract, DummyHost, Interpreter}, - primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, TxKind, U256}, + primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, EthChainSpec, TxKind, U256}, Evm, }; use revm_interpreter::{opcode::make_instruction_table, SharedMemory, EMPTY_SHARED_MEMORY}; @@ -81,7 +81,10 @@ fn transfer(c: &mut Criterion) { g.finish(); } -fn bench_transact(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm<'_, EXT, BenchmarkDB>) { +fn bench_transact( + g: &mut BenchmarkGroup<'_, WallTime>, + evm: &mut Evm<'_, EthChainSpec, EXT, BenchmarkDB>, +) { let state = match evm.context.evm.db.0 { Bytecode::LegacyRaw(_) => "raw", Bytecode::LegacyAnalyzed(_) => "analysed", @@ -91,7 +94,10 @@ fn bench_transact(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm<'_, E g.bench_function(id, |b| b.iter(|| evm.transact().unwrap())); } -fn bench_eval(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm<'static, (), BenchmarkDB>) { +fn bench_eval( + g: &mut BenchmarkGroup<'_, WallTime>, + evm: &mut Evm<'static, EthChainSpec, (), BenchmarkDB>, +) { g.bench_function("eval", |b| { let contract = Contract { input: evm.context.evm.env.tx.data.clone(), @@ -100,7 +106,7 @@ fn bench_eval(g: &mut BenchmarkGroup<'_, WallTime>, evm: &mut Evm<'static, (), B }; let mut shared_memory = SharedMemory::new(); let mut host = DummyHost::new(*evm.context.evm.env.clone()); - let instruction_table = make_instruction_table::(); + let instruction_table = make_instruction_table::, BerlinSpec>(); b.iter(move || { // replace memory with empty memory to use it inside interpreter. // Later return memory back. diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 1ce88486ba..bb5aca9bc0 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,10 +1,11 @@ use crate::{ db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, - handler::register, - primitives::{ - BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, HandlerCfg, SpecId, TxEnv, + handler::{ + register::{self, EvmHandler}, + CfgEnvWithChainSpec, EnvWithChainSpec, }, - Context, ContextWithHandlerCfg, Evm, Handler, + primitives::{CfgEnv, ChainSpec, Env, EthChainSpec}, + Context, ContextWithChainSpec, Evm, EvmContext, Handler, }; use core::marker::PhantomData; use std::boxed::Box; @@ -12,10 +13,10 @@ use std::boxed::Box; /// Evm Builder allows building or modifying EVM. /// Note that some of the methods that changes underlying structures /// will reset the registered handler to default mainnet. -pub struct EvmBuilder<'a, BuilderStage, EXT, DB: Database> { - context: Context, +pub struct EvmBuilder<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> { + context: Context, /// Handler that will be used by EVM. It contains handle registers - handler: Handler<'a, Context, EXT, DB>, + handler: Handler<'a, ChainSpecT, Context, EXT, DB>, /// Phantom data to mark the stage of the builder. phantom: PhantomData, } @@ -28,45 +29,55 @@ pub struct SetGenericStage; /// Requires the database and external context to be set. pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, SetGenericStage, (), EmptyDB> { +impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthChainSpec, (), EmptyDB> { fn default() -> Self { - cfg_if::cfg_if! { - if #[cfg(all(feature = "optimism-default-handler", - not(feature = "negate-optimism-default-handler")))] { - let mut handler_cfg = HandlerCfg::new(SpecId::LATEST); - // set is_optimism to true by default. - handler_cfg.is_optimism = true; - - } else { - let handler_cfg = HandlerCfg::new(SpecId::LATEST); - } - } - Self { context: Context::default(), - handler: EvmBuilder::<'a, SetGenericStage, (), EmptyDB>::handler(handler_cfg), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler( + ::Hardfork::default(), + ), phantom: PhantomData, } } } -impl<'a, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> + EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB> +{ + /// Sets the [`ChainSpec`] that will be used by [`Evm`]. + pub fn with_chain_spec( + self, + ) -> EvmBuilder<'a, SetGenericStage, NewChainSpecT, EXT, DB> { + let Context { evm, external } = self.context; + + EvmBuilder { + context: Context::new(EvmContext::new(evm.inner.db), external), + handler: EvmBuilder::<'_, SetGenericStage, NewChainSpecT, _, _>::handler( + NewChainSpecT::Hardfork::default(), + ), + phantom: PhantomData, + } + } + /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. - pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EXT, EmptyDB> { + pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, EmptyDB> { EvmBuilder { context: Context::new( self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: EvmBuilder::<'a, SetGenericStage, EXT, EmptyDB>::handler(self.handler.cfg()), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } /// Sets the [`Database`] that will be used by [`Evm`]. - pub fn with_db(self, db: ODB) -> EvmBuilder<'a, SetGenericStage, EXT, ODB> { + pub fn with_db( + self, + db: ODB, + ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, ODB> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: EvmBuilder::<'a, SetGenericStage, EXT, ODB>::handler(self.handler.cfg()), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } @@ -74,15 +85,13 @@ impl<'a, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EXT, DB> { pub fn with_ref_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EXT, WrapDatabaseRef> { + ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, WrapDatabaseRef> { EvmBuilder { context: Context::new( self.context.evm.with_db(WrapDatabaseRef(db)), self.context.external, ), - handler: EvmBuilder::<'a, SetGenericStage, EXT, WrapDatabaseRef>::handler( - self.handler.cfg(), - ), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } @@ -91,131 +100,86 @@ impl<'a, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EXT, DB> { pub fn with_external_context( self, external: OEXT, - ) -> EvmBuilder<'a, SetGenericStage, OEXT, DB> { + ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, OEXT, DB> { EvmBuilder { context: Context::new(self.context.evm, external), - handler: EvmBuilder::<'a, SetGenericStage, OEXT, DB>::handler(self.handler.cfg()), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } - /// Sets Builder with [`EnvWithHandlerCfg`]. + /// Sets Builder with [`EnvWithChainSpec`]. pub fn with_env_with_handler_cfg( mut self, - env_with_handler_cfg: EnvWithHandlerCfg, - ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { - let EnvWithHandlerCfg { env, handler_cfg } = env_with_handler_cfg; + env_with_handler_cfg: EnvWithChainSpec, + ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { + let EnvWithChainSpec { env, spec_id } = env_with_handler_cfg; self.context.evm.env = env; EvmBuilder { context: self.context, - handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler(handler_cfg), + handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler(spec_id), phantom: PhantomData, } } - /// Sets Builder with [`ContextWithHandlerCfg`]. + /// Sets Builder with [`ContextWithChainSpec`]. pub fn with_context_with_handler_cfg( self, - context_with_handler_cfg: ContextWithHandlerCfg, - ) -> EvmBuilder<'a, HandlerStage, OEXT, ODB> { + context_with_handler_cfg: ContextWithChainSpec, + ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, OEXT, ODB> { EvmBuilder { context: context_with_handler_cfg.context, - handler: EvmBuilder::<'a, HandlerStage, OEXT, ODB>::handler( - context_with_handler_cfg.cfg, + handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler( + context_with_handler_cfg.spec_id, ), phantom: PhantomData, } } - /// Sets Builder with [`CfgEnvWithHandlerCfg`]. + /// Sets Builder with [`CfgEnvWithChainSpec`]. pub fn with_cfg_env_with_handler_cfg( mut self, - cfg_env_and_spec_id: CfgEnvWithHandlerCfg, - ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + cfg_env_and_spec_id: CfgEnvWithChainSpec, + ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; EvmBuilder { context: self.context, - handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler( - cfg_env_and_spec_id.handler_cfg, - ), - phantom: PhantomData, - } - } - - /// Sets Builder with [`HandlerCfg`] - pub fn with_handler_cfg( - self, - handler_cfg: HandlerCfg, - ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { - EvmBuilder { - context: self.context, - handler: EvmBuilder::<'a, HandlerStage, EXT, DB>::handler(handler_cfg), - phantom: PhantomData, - } - } - - /// Sets the Optimism handler with latest spec. - /// - /// If `optimism-default-handler` feature is enabled this is not needed. - #[cfg(feature = "optimism")] - pub fn optimism(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { - self.handler = Handler::optimism_with_spec(self.handler.cfg.spec_id); - EvmBuilder { - context: self.context, - handler: self.handler, - phantom: PhantomData, - } - } - - /// Sets the mainnet handler with latest spec. - /// - /// Enabled only with `optimism-default-handler` feature. - #[cfg(feature = "optimism-default-handler")] - pub fn mainnet(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { - self.handler = Handler::mainnet_with_spec(self.handler.cfg.spec_id); - EvmBuilder { - context: self.context, - handler: self.handler, + handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler(cfg_env_and_spec_id.spec_id), phantom: PhantomData, } } } -impl<'a, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> + EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> +{ /// Creates new builder from Evm, Evm is consumed and all field are moved to Builder. /// It will preserve set handler and context. /// /// Builder is in HandlerStage and both database and external are set. - pub fn new(evm: Evm<'a, EXT, DB>) -> Self { + pub fn new(evm: Evm<'a, ChainSpecT, EXT, DB>) -> Self { Self { context: evm.context, handler: evm.handler, phantom: PhantomData, } } +} +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> + EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> +{ /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. - pub fn reset_handler_with_empty_db(self) -> EvmBuilder<'a, HandlerStage, EXT, EmptyDB> { + pub fn reset_handler_with_empty_db( + self, + ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, EmptyDB> { EvmBuilder { context: Context::new( self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: EvmBuilder::<'a, HandlerStage, EXT, EmptyDB>::handler(self.handler.cfg()), - phantom: PhantomData, - } - } - - /// Resets the [`Handler`] and sets base mainnet handler. - /// - /// Enabled only with `optimism-default-handler` feature. - #[cfg(feature = "optimism-default-handler")] - pub fn reset_handler_with_mainnet(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { - self.handler = Handler::mainnet_with_spec(self.handler.cfg.spec_id); - EvmBuilder { - context: self.context, - handler: self.handler, + handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } @@ -225,10 +189,10 @@ impl<'a, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EXT, DB> { pub fn reset_handler_with_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EXT, ODB> { + ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, ODB> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: EvmBuilder::<'a, SetGenericStage, EXT, ODB>::handler(self.handler.cfg()), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } @@ -238,15 +202,13 @@ impl<'a, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EXT, DB> { pub fn reset_handler_with_ref_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EXT, WrapDatabaseRef> { + ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, WrapDatabaseRef> { EvmBuilder { context: Context::new( self.context.evm.with_db(WrapDatabaseRef(db)), self.context.external, ), - handler: EvmBuilder::<'a, SetGenericStage, EXT, WrapDatabaseRef>::handler( - self.handler.cfg(), - ), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } @@ -256,34 +218,29 @@ impl<'a, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EXT, DB> { pub fn reset_handler_with_external_context( self, external: OEXT, - ) -> EvmBuilder<'a, SetGenericStage, OEXT, DB> { + ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, OEXT, DB> { EvmBuilder { context: Context::new(self.context.evm, external), - handler: EvmBuilder::<'a, SetGenericStage, OEXT, DB>::handler(self.handler.cfg()), + handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), phantom: PhantomData, } } } -impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> { - /// Creates the default handler. - /// - /// This is useful for adding optimism handle register. - fn handler(handler_cfg: HandlerCfg) -> Handler<'a, Context, EXT, DB> { - Handler::new(handler_cfg) - } - +impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> + EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +{ /// This modifies the [EvmBuilder] to make it easy to construct an [`Evm`] with a _specific_ /// handler. /// /// # Example /// ```rust - /// use revm::{EvmBuilder, Handler, primitives::{SpecId, HandlerCfg}}; + /// use revm::{EvmBuilder, EvmHandler, db::EmptyDB, primitives::{EthChainSpec, SpecId}}; /// use revm_interpreter::primitives::CancunSpec; /// let builder = EvmBuilder::default(); /// /// // get the desired handler - /// let mainnet = Handler::mainnet::(); + /// let mainnet = EvmHandler::<'_, EthChainSpec, (), EmptyDB>::mainnet_with_spec(SpecId::CANCUN); /// let builder = builder.with_handler(mainnet); /// /// // build the EVM @@ -291,8 +248,8 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> /// ``` pub fn with_handler( self, - handler: Handler<'a, Context, EXT, DB>, - ) -> EvmBuilder<'a, BuilderStage, EXT, DB> { + handler: Handler<'a, ChainSpecT, Context, EXT, DB>, + ) -> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> { EvmBuilder { context: self.context, handler, @@ -301,7 +258,7 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> } /// Builds the [`Evm`]. - pub fn build(self) -> Evm<'a, EXT, DB> { + pub fn build(self) -> Evm<'a, ChainSpecT, EXT, DB> { Evm::new(self.context, self.handler) } @@ -311,8 +268,8 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. pub fn append_handler_register( mut self, - handle_register: register::HandleRegister, - ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + handle_register: register::HandleRegister, + ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { self.handler .append_handler_register(register::HandleRegisters::Plain(handle_register)); EvmBuilder { @@ -329,8 +286,8 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. pub fn append_handler_register_box( mut self, - handle_register: register::HandleRegisterBox<'a, EXT, DB>, - ) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + handle_register: register::HandleRegisterBox<'a, ChainSpecT, EXT, DB>, + ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { self.handler .append_handler_register(register::HandleRegisters::Box(handle_register)); EvmBuilder { @@ -341,23 +298,6 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> } } - /// Sets specification Id , that will mark the version of EVM. - /// It represent the hard fork of ethereum. - /// - /// # Note - /// - /// When changed it will reapply all handle registers, this can be - /// expensive operation depending on registers. - pub fn with_spec_id(mut self, spec_id: SpecId) -> Self { - self.handler.modify_spec_id(spec_id); - EvmBuilder { - context: self.context, - handler: self.handler, - - phantom: PhantomData, - } - } - /// Allows modification of Evm Database. pub fn modify_db(mut self, f: impl FnOnce(&mut DB)) -> Self { f(&mut self.context.evm.db); @@ -371,37 +311,37 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> } /// Allows modification of Evm Environment. - pub fn modify_env(mut self, f: impl FnOnce(&mut Box)) -> Self { + pub fn modify_env(mut self, f: impl FnOnce(&mut Box>)) -> Self { f(&mut self.context.evm.env); self } /// Sets Evm Environment. - pub fn with_env(mut self, env: Box) -> Self { + pub fn with_env(mut self, env: Box>) -> Self { self.context.evm.env = env; self } /// Allows modification of Evm's Transaction Environment. - pub fn modify_tx_env(mut self, f: impl FnOnce(&mut TxEnv)) -> Self { + pub fn modify_tx_env(mut self, f: impl FnOnce(&mut ChainSpecT::Transaction)) -> Self { f(&mut self.context.evm.env.tx); self } /// Sets Evm's Transaction Environment. - pub fn with_tx_env(mut self, tx_env: TxEnv) -> Self { + pub fn with_tx_env(mut self, tx_env: ChainSpecT::Transaction) -> Self { self.context.evm.env.tx = tx_env; self } /// Allows modification of Evm's Block Environment. - pub fn modify_block_env(mut self, f: impl FnOnce(&mut BlockEnv)) -> Self { + pub fn modify_block_env(mut self, f: impl FnOnce(&mut ChainSpecT::Block)) -> Self { f(&mut self.context.evm.env.block); self } /// Sets Evm's Block Environment. - pub fn with_block_env(mut self, block_env: BlockEnv) -> Self { + pub fn with_block_env(mut self, block_env: ChainSpecT::Block) -> Self { self.context.evm.env.block = block_env; self } @@ -420,31 +360,58 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB> /// Clears Transaction environment of EVM. pub fn with_clear_tx_env(mut self) -> Self { - self.context.evm.env.tx.clear(); + self.context.evm.env.tx = ChainSpecT::Transaction::default(); self } /// Clears Block environment of EVM. pub fn with_clear_block_env(mut self) -> Self { - self.context.evm.env.block.clear(); + self.context.evm.env.block = ChainSpecT::Block::default(); self } +} + +impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> + EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +{ + /// Creates the default handler. + /// + /// This is useful for adding optimism handle register. + fn handler(spec_id: ChainSpecT::Hardfork) -> EvmHandler<'a, ChainSpecT, EXT, DB> { + Handler::mainnet_with_spec(spec_id) + } + + /// Sets specification Id , that will mark the version of EVM. + /// It represent the hard fork of ethereum. + /// + /// # Note + /// + /// When changed it will reapply all handle registers, this can be + /// expensive operation depending on registers. + pub fn with_spec_id(mut self, spec_id: ChainSpecT::Hardfork) -> Self { + self.handler.modify_spec_id(spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + + phantom: PhantomData, + } + } /// Resets [`Handler`] to default mainnet. pub fn reset_handler(mut self) -> Self { - self.handler = Self::handler(self.handler.cfg()); + self.handler = Self::handler(self.handler.spec_id()); self } } #[cfg(test)] mod test { - use super::SpecId; use crate::{ db::EmptyDB, inspector::inspector_handle_register, inspectors::NoOpInspector, primitives::{ - address, AccountInfo, Address, Bytecode, Bytes, PrecompileResult, TxKind, U256, + address, AccountInfo, Address, Bytecode, Bytes, PrecompileResult, SpecId, TxKind, U256, }, Context, ContextPrecompile, ContextStatefulPrecompile, Evm, InMemoryDB, InnerEvmContext, }; @@ -452,6 +419,11 @@ mod test { use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; + #[cfg(feature = "optimism")] + type TestChainSpec = crate::optimism::OptimismChainSpec; + #[cfg(not(feature = "optimism"))] + type TestChainSpec = crate::primitives::EthChainSpec; + /// Custom evm context #[derive(Default, Clone, Debug)] pub(crate) struct CustomContext { @@ -470,11 +442,19 @@ mod test { let to_capture = custom_context.clone(); let mut evm = Evm::builder() + .with_chain_spec::() .with_db(InMemoryDB::default()) .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) - .modify_tx_env(|tx| tx.transact_to = TxKind::Call(to_addr)) + .modify_tx_env(|tx| { + #[cfg(feature = "optimism")] + let transact_to = &mut tx.base.transact_to; + #[cfg(not(feature = "optimism"))] + let transact_to = &mut tx.transact_to; + + *transact_to = TxKind::Call(to_addr) + }) // we need to use handle register box to capture the custom context in the handle // register .append_handler_register_box(Box::new(move |handler| { @@ -482,7 +462,8 @@ mod test { // we need to use a box to capture the custom context in the instruction let custom_instruction = Box::new( - move |_interp: &mut Interpreter, _host: &mut Context<(), InMemoryDB>| { + move |_interp: &mut Interpreter, + _host: &mut Context| { // modify the value let mut inner = custom_context.inner.borrow_mut(); *inner += 1; @@ -519,11 +500,19 @@ mod test { let to_addr = address!("ffffffffffffffffffffffffffffffffffffffff"); let mut evm = Evm::builder() + .with_chain_spec::() .with_db(InMemoryDB::default()) .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) - .modify_tx_env(|tx| tx.transact_to = TxKind::Call(to_addr)) + .modify_tx_env(|tx| { + #[cfg(feature = "optimism")] + let transact_to = &mut tx.base.transact_to; + #[cfg(not(feature = "optimism"))] + let transact_to = &mut tx.transact_to; + + *transact_to = TxKind::Call(to_addr) + }) .append_handler_register(|handler| { handler.instruction_table.insert(0xED, custom_instruction) }) @@ -536,15 +525,25 @@ mod test { #[test] fn simple_build() { // build without external with latest spec - Evm::builder().build(); + Evm::builder().with_chain_spec::().build(); // build with empty db - Evm::builder().with_empty_db().build(); + Evm::builder() + .with_chain_spec::() + .with_empty_db() + .build(); // build with_db - Evm::builder().with_db(EmptyDB::default()).build(); + Evm::builder() + .with_chain_spec::() + .with_db(EmptyDB::default()) + .build(); // build with empty external - Evm::builder().with_empty_db().build(); + Evm::builder() + .with_chain_spec::() + .with_empty_db() + .build(); // build with some external Evm::builder() + .with_chain_spec::() .with_empty_db() .with_external_context(()) .build(); @@ -556,21 +555,56 @@ mod test { // with with Env change in multiple places Evm::builder() + .with_chain_spec::() .with_empty_db() - .modify_tx_env(|tx| tx.gas_limit = 10) + .modify_tx_env(|tx| { + #[cfg(feature = "optimism")] + let gas_limit = &mut tx.base.gas_limit; + #[cfg(not(feature = "optimism"))] + let gas_limit = &mut tx.gas_limit; + + *gas_limit = 10 + }) + .build(); + Evm::builder() + .with_chain_spec::() + .modify_tx_env(|tx| { + #[cfg(feature = "optimism")] + let gas_limit = &mut tx.base.gas_limit; + #[cfg(not(feature = "optimism"))] + let gas_limit = &mut tx.gas_limit; + + *gas_limit = 10 + }) .build(); - Evm::builder().modify_tx_env(|tx| tx.gas_limit = 10).build(); Evm::builder() + .with_chain_spec::() .with_empty_db() - .modify_tx_env(|tx| tx.gas_limit = 10) + .modify_tx_env(|tx| { + #[cfg(feature = "optimism")] + let gas_limit = &mut tx.base.gas_limit; + #[cfg(not(feature = "optimism"))] + let gas_limit = &mut tx.gas_limit; + + *gas_limit = 10 + }) .build(); Evm::builder() + .with_chain_spec::() .with_empty_db() - .modify_tx_env(|tx| tx.gas_limit = 10) + .modify_tx_env(|tx| { + #[cfg(feature = "optimism")] + let gas_limit = &mut tx.base.gas_limit; + #[cfg(not(feature = "optimism"))] + let gas_limit = &mut tx.gas_limit; + + *gas_limit = 10 + }) .build(); // with inspector handle Evm::builder() + .with_chain_spec::() .with_empty_db() .with_external_context(NoOpInspector) .append_handler_register(inspector_handle_register) @@ -579,6 +613,7 @@ mod test { // create the builder let evm = Evm::builder() .with_db(EmptyDB::default()) + .with_chain_spec::() .with_external_context(NoOpInspector) .append_handler_register(inspector_handle_register) // this would not compile @@ -608,20 +643,25 @@ mod test { fn build_custom_precompile() { struct CustomPrecompile; - impl ContextStatefulPrecompile for CustomPrecompile { + impl ContextStatefulPrecompile for CustomPrecompile { fn call( &self, _input: &Bytes, _gas_limit: u64, - _context: &mut InnerEvmContext, + _context: &mut InnerEvmContext, ) -> PrecompileResult { Ok(PrecompileOutput::new(10, Bytes::new())) } } + #[cfg(feature = "optimism")] + let spec_id = crate::optimism::OptimismSpecId::HOMESTEAD; + #[cfg(not(feature = "optimism"))] + let spec_id = crate::primitives::SpecId::HOMESTEAD; + let mut evm = Evm::builder() - .with_empty_db() - .with_spec_id(SpecId::HOMESTEAD) + .with_chain_spec::() + .with_spec_id(spec_id) .append_handler_register(|handler| { let precompiles = handler.pre_execution.load_precompiles(); handler.pre_execution.load_precompiles = Arc::new(move || { diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index d715296b43..d9685a058a 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -13,19 +13,22 @@ use revm_interpreter::as_usize_saturated; use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, - primitives::{Address, Bytes, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256}, + primitives::{ + Address, Block as _, Bytes, ChainSpec, Env, EthChainSpec, Log, B256, BLOCK_HASH_HISTORY, + U256, + }, }; use std::boxed::Box; /// Main Context structure that contains both EvmContext and External context. -pub struct Context { +pub struct Context { /// Evm Context (internal context). - pub evm: EvmContext, + pub evm: EvmContext, /// External contexts. pub external: EXT, } -impl Clone for Context +impl Clone for Context where DB::Error: Clone, { @@ -37,15 +40,15 @@ where } } -impl Default for Context<(), EmptyDB> { +impl Default for Context { fn default() -> Self { Self::new_empty() } } -impl Context<(), EmptyDB> { +impl Context { /// Creates empty context. This is useful for testing. - pub fn new_empty() -> Context<(), EmptyDB> { + pub fn new_empty() -> Context { Context { evm: EvmContext::new(EmptyDB::new()), external: (), @@ -53,9 +56,9 @@ impl Context<(), EmptyDB> { } } -impl Context<(), DB> { +impl Context { /// Creates new context with database. - pub fn new_with_db(db: DB) -> Context<(), DB> { + pub fn new_with_db(db: DB) -> Context { Context { evm: EvmContext::new_with_env(db, Box::default()), external: (), @@ -63,53 +66,56 @@ impl Context<(), DB> { } } -impl Context { +impl Context { /// Creates new context with external and database. - pub fn new(evm: EvmContext, external: EXT) -> Context { + pub fn new(evm: EvmContext, external: EXT) -> Context { Context { evm, external } } } /// Context with handler configuration. -pub struct ContextWithHandlerCfg { +pub struct ContextWithChainSpec { /// Context of execution. - pub context: Context, + pub context: Context, /// Handler configuration. - pub cfg: HandlerCfg, + pub spec_id: ChainSpecT::Hardfork, } -impl ContextWithHandlerCfg { +impl ContextWithChainSpec { /// Creates new context with handler configuration. - pub fn new(context: Context, cfg: HandlerCfg) -> Self { - Self { cfg, context } + pub fn new(context: Context, spec_id: ChainSpecT::Hardfork) -> Self { + Self { spec_id, context } } } -impl Clone for ContextWithHandlerCfg +impl Clone + for ContextWithChainSpec where DB::Error: Clone, { fn clone(&self) -> Self { Self { context: self.context.clone(), - cfg: self.cfg, + spec_id: self.spec_id, } } } -impl Host for Context { +impl Host for Context { + type ChainSpecT = ChainSpecT; + /// Returns reference to Environment. #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &Env { &self.evm.env } - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut Env { &mut self.evm.env } fn block_hash(&mut self, number: u64) -> Option { - let block_number = as_usize_saturated!(self.env().block.number); + let block_number = as_usize_saturated!(self.env().block.number()); let requested_number = usize::try_from(number).unwrap_or(usize::MAX); let Some(diff) = block_number.checked_sub(requested_number) else { diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index f674093535..c1e866d093 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -1,25 +1,25 @@ use super::InnerEvmContext; use crate::{ precompile::{Precompile, PrecompileResult}, - primitives::{db::Database, Address, Bytes, HashMap, HashSet}, + primitives::{db::Database, Address, Bytes, ChainSpec, HashMap, HashSet}, }; use dyn_clone::DynClone; use revm_precompile::{PrecompileSpecId, PrecompileWithAddress, Precompiles}; use std::{boxed::Box, sync::Arc}; /// A single precompile handler. -pub enum ContextPrecompile { +pub enum ContextPrecompile { /// Ordinary precompiles Ordinary(Precompile), /// Stateful precompile that is Arc over [`ContextStatefulPrecompile`] trait. /// It takes a reference to input, gas limit and Context. - ContextStateful(ContextStatefulPrecompileArc), + ContextStateful(ContextStatefulPrecompileArc), /// Mutable stateful precompile that is Box over [`ContextStatefulPrecompileMut`] trait. /// It takes a reference to input, gas limit and context. - ContextStatefulMut(ContextStatefulPrecompileBox), + ContextStatefulMut(ContextStatefulPrecompileBox), } -impl Clone for ContextPrecompile { +impl Clone for ContextPrecompile { fn clone(&self) -> Self { match self { Self::Ordinary(p) => Self::Ordinary(p.clone()), @@ -29,13 +29,13 @@ impl Clone for ContextPrecompile { } } -enum PrecompilesCow { +enum PrecompilesCow { /// Default precompiles, returned by `Precompiles::new`. Used to fast-path the default case. StaticRef(&'static Precompiles), - Owned(HashMap>), + Owned(HashMap>), } -impl Clone for PrecompilesCow { +impl Clone for PrecompilesCow { fn clone(&self) -> Self { match *self { PrecompilesCow::StaticRef(p) => PrecompilesCow::StaticRef(p), @@ -45,11 +45,11 @@ impl Clone for PrecompilesCow { } /// Precompiles context. -pub struct ContextPrecompiles { - inner: PrecompilesCow, +pub struct ContextPrecompiles { + inner: PrecompilesCow, } -impl Clone for ContextPrecompiles { +impl Clone for ContextPrecompiles { fn clone(&self) -> Self { Self { inner: self.inner.clone(), @@ -57,7 +57,7 @@ impl Clone for ContextPrecompiles { } } -impl ContextPrecompiles { +impl ContextPrecompiles { /// Creates a new precompiles context at the given spec ID. /// /// This is a cheap operation that does not allocate by reusing the global precompiles. @@ -79,7 +79,9 @@ impl ContextPrecompiles { /// Creates a new precompiles context from the given precompiles. #[inline] - pub fn from_precompiles(precompiles: HashMap>) -> Self { + pub fn from_precompiles( + precompiles: HashMap>, + ) -> Self { Self { inner: PrecompilesCow::Owned(precompiles), } @@ -120,12 +122,14 @@ impl ContextPrecompiles { address: &Address, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> Option { Some(match self.inner { - PrecompilesCow::StaticRef(p) => p.get(address)?.call_ref(bytes, gas_limit, &evmctx.env), + PrecompilesCow::StaticRef(p) => { + p.get(address)?.call_ref(bytes, gas_limit, &evmctx.env.cfg) + } PrecompilesCow::Owned(ref mut owned) => match owned.get_mut(address)? { - ContextPrecompile::Ordinary(p) => p.call(bytes, gas_limit, &evmctx.env), + ContextPrecompile::Ordinary(p) => p.call(bytes, gas_limit, &evmctx.env.cfg), ContextPrecompile::ContextStateful(p) => p.call(bytes, gas_limit, evmctx), ContextPrecompile::ContextStatefulMut(p) => p.call_mut(bytes, gas_limit, evmctx), }, @@ -136,7 +140,7 @@ impl ContextPrecompiles { /// /// Clones the precompiles map if it is shared. #[inline] - pub fn to_mut(&mut self) -> &mut HashMap> { + pub fn to_mut(&mut self) -> &mut HashMap> { if let PrecompilesCow::StaticRef(_) = self.inner { self.mutate_into_owned(); } @@ -164,13 +168,20 @@ impl ContextPrecompiles { } } -impl Extend<(Address, ContextPrecompile)> for ContextPrecompiles { - fn extend)>>(&mut self, iter: T) { +impl Extend<(Address, ContextPrecompile)> + for ContextPrecompiles +{ + fn extend)>>( + &mut self, + iter: T, + ) { self.to_mut().extend(iter.into_iter().map(Into::into)) } } -impl Extend for ContextPrecompiles { +impl Extend + for ContextPrecompiles +{ fn extend>(&mut self, iter: T) { self.to_mut().extend(iter.into_iter().map(|precompile| { let (address, precompile) = precompile.into(); @@ -179,7 +190,7 @@ impl Extend for ContextPrecompiles { } } -impl Default for ContextPrecompiles { +impl Default for ContextPrecompiles { fn default() -> Self { Self { inner: Default::default(), @@ -187,7 +198,7 @@ impl Default for ContextPrecompiles { } } -impl Default for PrecompilesCow { +impl Default for PrecompilesCow { fn default() -> Self { Self::Owned(Default::default()) } @@ -195,35 +206,39 @@ impl Default for PrecompilesCow { /// Context aware stateful precompile trait. It is used to create /// a arc precompile in [`ContextPrecompile`]. -pub trait ContextStatefulPrecompile: Sync + Send { +pub trait ContextStatefulPrecompile: Sync + Send { fn call( &self, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> PrecompileResult; } /// Context aware mutable stateful precompile trait. It is used to create /// a boxed precompile in [`ContextPrecompile`]. -pub trait ContextStatefulPrecompileMut: DynClone + Send + Sync { +pub trait ContextStatefulPrecompileMut: + DynClone + Send + Sync +{ fn call_mut( &mut self, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> PrecompileResult; } -dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); +dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); /// Arc over context stateful precompile. -pub type ContextStatefulPrecompileArc = Arc>; +pub type ContextStatefulPrecompileArc = + Arc>; /// Box over context mutable stateful precompile -pub type ContextStatefulPrecompileBox = Box>; +pub type ContextStatefulPrecompileBox = + Box>; -impl From for ContextPrecompile { +impl From for ContextPrecompile { fn from(p: Precompile) -> Self { ContextPrecompile::Ordinary(p) } @@ -232,13 +247,14 @@ impl From for ContextPrecompile { #[cfg(test)] mod tests { use super::*; - use crate::db::EmptyDB; + use crate::{db::EmptyDB, primitives::EthChainSpec}; #[test] fn test_precompiles_context() { let custom_address = Address::with_last_byte(0xff); - let mut precompiles = ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); + let mut precompiles = + ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); assert_eq!(precompiles.addresses().count(), 4); assert!(matches!(precompiles.inner, PrecompilesCow::StaticRef(_))); assert!(!precompiles.contains(&custom_address)); diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 9e322a3a60..efaafa5e72 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -9,9 +9,9 @@ use crate::{ EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, primitives::{ - keccak256, Address, Bytecode, Bytes, CreateScheme, EVMError, Env, Eof, + keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, Env, Eof, SpecId::{self, *}, - B256, EOF_MAGIC_BYTES, + Transaction as _, B256, EOF_MAGIC_BYTES, }, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; @@ -22,15 +22,16 @@ use core::{ use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. -pub struct EvmContext { +pub struct EvmContext { /// Inner EVM context. - pub inner: InnerEvmContext, + pub inner: InnerEvmContext, /// Precompiles that are available for evm. - pub precompiles: ContextPrecompiles, + pub precompiles: ContextPrecompiles, } -impl Clone for EvmContext +impl Clone for EvmContext where + ChainSpecT: ChainSpec, DB::Error: Clone, { fn clone(&self) -> Self { @@ -41,8 +42,9 @@ where } } -impl fmt::Debug for EvmContext +impl fmt::Debug for EvmContext where + ChainSpecT: ChainSpec, DB: Database + fmt::Debug, DB::Error: fmt::Debug, { @@ -54,21 +56,21 @@ where } } -impl Deref for EvmContext { - type Target = InnerEvmContext; +impl Deref for EvmContext { + type Target = InnerEvmContext; fn deref(&self) -> &Self::Target { &self.inner } } -impl DerefMut for EvmContext { +impl DerefMut for EvmContext { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -impl EvmContext { +impl EvmContext { /// Create new context with database. pub fn new(db: DB) -> Self { Self { @@ -79,7 +81,7 @@ impl EvmContext { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: DB, env: Box) -> Self { + pub fn new_with_env(db: DB, env: Box>) -> Self { Self { inner: InnerEvmContext::new_with_env(db, env), precompiles: ContextPrecompiles::default(), @@ -90,7 +92,7 @@ impl EvmContext { /// /// Note that this will ignore the previous `error` if set. #[inline] - pub fn with_db(self, db: ODB) -> EvmContext { + pub fn with_db(self, db: ODB) -> EvmContext { EvmContext { inner: self.inner.with_db(db), precompiles: ContextPrecompiles::default(), @@ -99,7 +101,7 @@ impl EvmContext { /// Sets precompiles #[inline] - pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { + pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { // set warm loaded addresses. self.journaled_state .warm_preloaded_addresses @@ -114,7 +116,7 @@ impl EvmContext { address: &Address, input_data: &Bytes, gas: Gas, - ) -> Result, EVMError> { + ) -> Result, EVMError> { let Some(outcome) = self.precompiles .call(address, input_data, gas.limit(), &mut self.inner) @@ -154,7 +156,7 @@ impl EvmContext { pub fn make_call_frame( &mut self, inputs: &CallInputs, - ) -> Result> { + ) -> Result> { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -177,7 +179,8 @@ impl EvmContext { let _ = self .inner .journaled_state - .load_account(inputs.bytecode_address, &mut self.inner.db)?; + .load_account(inputs.bytecode_address, &mut self.inner.db) + .map_err(EVMError::Database)?; // Create subroutine checkpoint let checkpoint = self.journaled_state.checkpoint(); @@ -186,18 +189,24 @@ impl EvmContext { match inputs.value { // if transfer value is zero, load account and force the touch. CallValue::Transfer(value) if value.is_zero() => { - self.load_account(inputs.target_address)?; + self.load_account(inputs.target_address) + .map_err(EVMError::Database)?; self.journaled_state.touch(&inputs.target_address); } CallValue::Transfer(value) => { // Transfer value from caller to called account. As value get transferred // target gets touched. - if let Some(result) = self.inner.journaled_state.transfer( - &inputs.caller, - &inputs.target_address, - value, - &mut self.inner.db, - )? { + if let Some(result) = self + .inner + .journaled_state + .transfer( + &inputs.caller, + &inputs.target_address, + value, + &mut self.inner.db, + ) + .map_err(EVMError::Database)? + { self.journaled_state.checkpoint_revert(checkpoint); return return_result(result); } @@ -219,7 +228,8 @@ impl EvmContext { let (account, _) = self .inner .journaled_state - .load_code(inputs.bytecode_address, &mut self.inner.db)?; + .load_code(inputs.bytecode_address, &mut self.inner.db) + .map_err(EVMError::Database)?; let code_hash = account.info.code_hash(); let bytecode = account.info.code.clone().unwrap_or_default(); @@ -253,7 +263,7 @@ impl EvmContext { &mut self, spec_id: SpecId, inputs: &CreateInputs, - ) -> Result> { + ) -> Result { let return_error = |e| { Ok(FrameOrResult::new_create_result( InterpreterResult { @@ -347,7 +357,7 @@ impl EvmContext { &mut self, spec_id: SpecId, inputs: &EOFCreateInputs, - ) -> Result> { + ) -> Result { let return_error = |e| { Ok(FrameOrResult::new_eofcreate_result( InterpreterResult { @@ -381,8 +391,8 @@ impl EvmContext { let nonce = self .env .tx - .nonce - .map(|nonce| self.env.tx.caller.create(nonce)); + .nonce() + .map(|nonce| self.env.tx.caller().create(nonce)); (input, eof, nonce) } @@ -487,11 +497,11 @@ pub(crate) mod test_utils { /// Creates an evm context with a cache db backend. /// Additionally loads the mock caller account into the db, /// and sets the balance to the provided U256 value. - pub fn create_cache_db_evm_context_with_balance( - env: Box, + pub fn create_cache_db_evm_context_with_balance( + env: Box>, mut db: CacheDB, balance: U256, - ) -> EvmContext> { + ) -> EvmContext> { db.insert_account_info( test_utils::MOCK_CALLER, crate::primitives::AccountInfo { @@ -505,10 +515,10 @@ pub(crate) mod test_utils { } /// Creates a cached db evm context. - pub fn create_cache_db_evm_context( - env: Box, + pub fn create_cache_db_evm_context( + env: Box>, db: CacheDB, - ) -> EvmContext> { + ) -> EvmContext> { EvmContext { inner: InnerEvmContext { env, @@ -516,15 +526,16 @@ pub(crate) mod test_utils { db, error: Ok(()), valid_authorizations: Vec::new(), - #[cfg(feature = "optimism")] - l1_block_info: None, }, precompiles: ContextPrecompiles::default(), } } /// Returns a new `EvmContext` with an empty journaled state. - pub fn create_empty_evm_context(env: Box, db: EmptyDB) -> EvmContext { + pub fn create_empty_evm_context( + env: Box>, + db: EmptyDB, + ) -> EvmContext { EvmContext { inner: InnerEvmContext { env, @@ -532,8 +543,6 @@ pub(crate) mod test_utils { db, error: Ok(()), valid_authorizations: Default::default(), - #[cfg(feature = "optimism")] - l1_block_info: None, }, precompiles: ContextPrecompiles::default(), } @@ -546,7 +555,7 @@ mod tests { use crate::primitives::U256; use crate::{ db::{CacheDB, EmptyDB}, - primitives::{address, Bytecode}, + primitives::{address, Bytecode, EthChainSpec}, Frame, JournalEntry, }; use std::boxed::Box; @@ -556,7 +565,7 @@ mod tests { // call stack is too deep. #[test] fn test_make_call_frame_stack_too_deep() { - let env = Env::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut context = test_utils::create_empty_evm_context(Box::new(env), db); context.journaled_state.depth = CALL_STACK_LIMIT as usize + 1; @@ -577,7 +586,7 @@ mod tests { // checkpointed on the journaled state correctly. #[test] fn test_make_call_frame_transfer_revert() { - let env = Env::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut evm_context = test_utils::create_empty_evm_context(Box::new(env), db); let contract = address!("dead10000000000000000000000000000001dead"); @@ -598,7 +607,7 @@ mod tests { #[test] fn test_make_call_frame_missing_code_context() { - let env = Env::default(); + let env = Env::::default(); let cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let mut context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); @@ -613,7 +622,7 @@ mod tests { #[test] fn test_make_call_frame_succeeds() { - let env = Env::default(); + let env = Env::::default(); let mut cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let by = Bytecode::new_raw(Bytes::from(vec![0x60, 0x00, 0x60, 0x00])); diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 93861cdd61..1b27cdf673 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -6,10 +6,10 @@ use crate::{ }, journaled_state::JournaledState, primitives::{ - AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, EVMError, Env, + AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, ChainSpec, Env, Eof, HashSet, Spec, SpecId::{self, *}, - B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, + Transaction as _, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, JournalCheckpoint, }; @@ -17,24 +17,21 @@ use std::{boxed::Box, sync::Arc, vec::Vec}; /// EVM contexts contains data that EVM needs for execution. #[derive(Debug)] -pub struct InnerEvmContext { +pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. - pub env: Box, + pub env: Box>, /// EVM State with journaling support. pub journaled_state: JournaledState, /// Database to load data from. pub db: DB, /// Error that happened during execution. - pub error: Result<(), EVMError>, + pub error: Result<(), DB::Error>, /// EIP-7702 Authorization list of accounts that needs to be cleared. pub valid_authorizations: Vec
, - /// Used as temporary value holder to store L1 block info. - #[cfg(feature = "optimism")] - pub l1_block_info: Option, } -impl Clone for InnerEvmContext +impl Clone for InnerEvmContext where DB::Error: Clone, { @@ -45,13 +42,11 @@ where db: self.db.clone(), error: self.error.clone(), valid_authorizations: self.valid_authorizations.clone(), - #[cfg(feature = "optimism")] - l1_block_info: self.l1_block_info.clone(), } } } -impl InnerEvmContext { +impl InnerEvmContext { pub fn new(db: DB) -> Self { Self { env: Box::default(), @@ -59,22 +54,18 @@ impl InnerEvmContext { db, error: Ok(()), valid_authorizations: Default::default(), - #[cfg(feature = "optimism")] - l1_block_info: None, } } /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: DB, env: Box) -> Self { + pub fn new_with_env(db: DB, env: Box>) -> Self { Self { env, journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), db, error: Ok(()), valid_authorizations: Default::default(), - #[cfg(feature = "optimism")] - l1_block_info: None, } } @@ -82,15 +73,13 @@ impl InnerEvmContext { /// /// Note that this will ignore the previous `error` if set. #[inline] - pub fn with_db(self, db: ODB) -> InnerEvmContext { + pub fn with_db(self, db: ODB) -> InnerEvmContext { InnerEvmContext { env: self.env, journaled_state: self.journaled_state, db, error: Ok(()), valid_authorizations: Default::default(), - #[cfg(feature = "optimism")] - l1_block_info: self.l1_block_info, } } @@ -104,11 +93,11 @@ impl InnerEvmContext { /// /// Loading of accounts/storages is needed to make them warm. #[inline] - pub fn load_access_list(&mut self) -> Result<(), EVMError> { + pub fn load_access_list(&mut self) -> Result<(), DB::Error> { for AccessListItem { address, storage_keys, - } in self.env.tx.access_list.iter() + } in self.env.tx.access_list() { self.journaled_state.initial_account_load( *address, @@ -121,7 +110,7 @@ impl InnerEvmContext { /// Return environment. #[inline] - pub fn env(&mut self) -> &mut Env { + pub fn env(&mut self) -> &mut Env { &mut self.env } @@ -132,14 +121,14 @@ impl InnerEvmContext { /// Returns the error by replacing it with `Ok(())`, if any. #[inline] - pub fn take_error(&mut self) -> Result<(), EVMError> { + pub fn take_error(&mut self) -> Result<(), DB::Error> { core::mem::replace(&mut self.error, Ok(())) } /// Fetch block hash from database. #[inline] - pub fn block_hash(&mut self, number: u64) -> Result> { - self.db.block_hash(number).map_err(EVMError::Database) + pub fn block_hash(&mut self, number: u64) -> Result { + self.db.block_hash(number) } /// Mark account as touched as only touched accounts will be added to state. @@ -150,10 +139,7 @@ impl InnerEvmContext { /// Loads an account into memory. Returns `true` if it is cold accessed. #[inline] - pub fn load_account( - &mut self, - address: Address, - ) -> Result<(&mut Account, bool), EVMError> { + pub fn load_account(&mut self, address: Address) -> Result<(&mut Account, bool), DB::Error> { self.journaled_state.load_account(address, &mut self.db) } @@ -161,17 +147,14 @@ impl InnerEvmContext { /// /// Return boolean pair where first is `is_cold` second bool `exists`. #[inline] - pub fn load_account_exist( - &mut self, - address: Address, - ) -> Result> { + pub fn load_account_exist(&mut self, address: Address) -> Result { self.journaled_state .load_account_exist(address, &mut self.db) } /// Return account balance and is_cold flag. #[inline] - pub fn balance(&mut self, address: Address) -> Result<(U256, bool), EVMError> { + pub fn balance(&mut self, address: Address) -> Result<(U256, bool), DB::Error> { self.journaled_state .load_account(address, &mut self.db) .map(|(acc, is_cold)| (acc.info.balance, is_cold)) @@ -181,7 +164,7 @@ impl InnerEvmContext { /// /// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code. #[inline] - pub fn code(&mut self, address: Address) -> Result<(Bytes, bool), EVMError> { + pub fn code(&mut self, address: Address) -> Result<(Bytes, bool), DB::Error> { self.journaled_state .load_code(address, &mut self.db) .map(|(a, is_cold)| { @@ -200,7 +183,7 @@ impl InnerEvmContext { /// In case of EOF account it will return `EOF_MAGIC_HASH` /// (the hash of `0xEF00`). #[inline] - pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), EVMError> { + pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), DB::Error> { let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?; if acc.is_empty() { return Ok((B256::ZERO, is_cold)); @@ -213,11 +196,7 @@ impl InnerEvmContext { /// Load storage slot, if storage is not present inside the account then it will be loaded from database. #[inline] - pub fn sload( - &mut self, - address: Address, - index: U256, - ) -> Result<(U256, bool), EVMError> { + pub fn sload(&mut self, address: Address, index: U256) -> Result<(U256, bool), DB::Error> { // account is always warm. reference on that statement https://eips.ethereum.org/EIPS/eip-2929 see `Note 2:` self.journaled_state.sload(address, index, &mut self.db) } @@ -229,7 +208,7 @@ impl InnerEvmContext { address: Address, index: U256, value: U256, - ) -> Result> { + ) -> Result { self.journaled_state .sstore(address, index, value, &mut self.db) } @@ -252,7 +231,7 @@ impl InnerEvmContext { &mut self, address: Address, target: Address, - ) -> Result> { + ) -> Result { self.journaled_state .selfdestruct(address, target, &mut self.db) } diff --git a/crates/revm/src/custom_upcode.rs b/crates/revm/src/custom_upcode.rs new file mode 100644 index 0000000000..4cdb5b2d43 --- /dev/null +++ b/crates/revm/src/custom_upcode.rs @@ -0,0 +1,260 @@ +use revm_interpreter::{ + gas, + opcode::{make_instruction_table, InstructionTable, InstructionTables}, + Host, Interpreter, +}; + +use crate::{ + handler::register::EvmHandler, + primitives::{db::Database, ChainSpec, HaltReason, Spec, SpecId}, +}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct CustomOpcodeChainSpec; + +impl ChainSpec for CustomOpcodeChainSpec { + type Hardfork = CustomOpcodeSpecId; + type HaltReason = HaltReason; +} + +/// Specification IDs for the optimism blockchain. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +pub enum CustomOpcodeSpecId { + FRONTIER = 0, + FRONTIER_THAWING = 1, + HOMESTEAD = 2, + DAO_FORK = 3, + TANGERINE = 4, + SPURIOUS_DRAGON = 5, + BYZANTIUM = 6, + CONSTANTINOPLE = 7, + PETERSBURG = 8, + ISTANBUL = 9, + MUIR_GLACIER = 10, + BERLIN = 11, + LONDON = 12, + ARROW_GLACIER = 13, + GRAY_GLACIER = 14, + MERGE = 15, + // Introduces the custom opcode in between the existing hardforks. + INTRODUCES_OPCODE = 16, + SHANGHAI = 17, + CANCUN = 18, + PRAGUE = 19, + #[default] + LATEST = u8::MAX, +} + +impl CustomOpcodeSpecId { + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + pub const fn enabled(our: Self, other: Self) -> bool { + our as u8 >= other as u8 + } + + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + pub const fn is_enabled_in(self, other: Self) -> bool { + Self::enabled(self, other) + } + + /// Converts the `CustomOpcodeSpecId` into an `SpecId`. + const fn into_eth_spec_id(self) -> SpecId { + match self { + Self::FRONTIER => SpecId::FRONTIER, + Self::FRONTIER_THAWING => SpecId::FRONTIER_THAWING, + Self::HOMESTEAD => SpecId::HOMESTEAD, + Self::DAO_FORK => SpecId::DAO_FORK, + Self::TANGERINE => SpecId::TANGERINE, + Self::SPURIOUS_DRAGON => SpecId::SPURIOUS_DRAGON, + Self::BYZANTIUM => SpecId::BYZANTIUM, + Self::CONSTANTINOPLE => SpecId::CONSTANTINOPLE, + Self::PETERSBURG => SpecId::PETERSBURG, + Self::ISTANBUL => SpecId::ISTANBUL, + Self::MUIR_GLACIER => SpecId::MUIR_GLACIER, + Self::BERLIN => SpecId::BERLIN, + Self::LONDON => SpecId::LONDON, + Self::ARROW_GLACIER => SpecId::ARROW_GLACIER, + Self::GRAY_GLACIER => SpecId::GRAY_GLACIER, + Self::MERGE | Self::INTRODUCES_OPCODE => SpecId::MERGE, + Self::SHANGHAI => SpecId::SHANGHAI, + Self::CANCUN => SpecId::CANCUN, + Self::PRAGUE => SpecId::PRAGUE, + Self::LATEST => SpecId::LATEST, + } + } +} + +impl From for SpecId { + fn from(spec_id: CustomOpcodeSpecId) -> Self { + spec_id.into_eth_spec_id() + } +} + +pub trait CustomOpcodeSpec: Spec + Sized + 'static { + /// The specification ID for an imaginary chain with custom opcodes. + const CUSTOM_OPCODE_SPEC_ID: CustomOpcodeSpecId; + + /// Returns whether the provided `CustomOpcodeSpec` is enabled by this spec. + #[inline] + fn optimism_enabled(spec_id: CustomOpcodeSpecId) -> bool { + CustomOpcodeSpecId::enabled(Self::CUSTOM_OPCODE_SPEC_ID, spec_id) + } +} + +macro_rules! spec { + ($spec_id:ident, $spec_name:ident) => { + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $spec_name; + + impl CustomOpcodeSpec for $spec_name { + const CUSTOM_OPCODE_SPEC_ID: CustomOpcodeSpecId = CustomOpcodeSpecId::$spec_id; + } + + impl Spec for $spec_name { + const SPEC_ID: SpecId = $spec_name::CUSTOM_OPCODE_SPEC_ID.into_eth_spec_id(); + } + }; +} + +spec!(FRONTIER, FrontierSpec); +// FRONTIER_THAWING no EVM spec change +spec!(HOMESTEAD, HomesteadSpec); +// DAO_FORK no EVM spec change +spec!(TANGERINE, TangerineSpec); +spec!(SPURIOUS_DRAGON, SpuriousDragonSpec); +spec!(BYZANTIUM, ByzantiumSpec); +// CONSTANTINOPLE was overridden with PETERSBURG +spec!(PETERSBURG, PetersburgSpec); +spec!(ISTANBUL, IstanbulSpec); +// MUIR_GLACIER no EVM spec change +spec!(BERLIN, BerlinSpec); +spec!(LONDON, LondonSpec); +// ARROW_GLACIER no EVM spec change +// GRAY_GLACIER no EVM spec change +spec!(MERGE, MergeSpec); +spec!(SHANGHAI, ShanghaiSpec); +spec!(CANCUN, CancunSpec); +spec!(PRAGUE, PragueSpec); + +spec!(LATEST, LatestSpec); + +// Custom Hardforks +spec!(INTRODUCES_OPCODE, IntroducesOpcodeSpec); + +macro_rules! custom_opcode_spec_to_generic { + ($spec_id:expr, $e:expr) => {{ + // We are transitioning from var to generic spec. + match $spec_id { + CustomOpcodeSpecId::FRONTIER | CustomOpcodeSpecId::FRONTIER_THAWING => { + use FrontierSpec as SPEC; + $e + } + CustomOpcodeSpecId::HOMESTEAD | CustomOpcodeSpecId::DAO_FORK => { + use HomesteadSpec as SPEC; + $e + } + CustomOpcodeSpecId::TANGERINE => { + use TangerineSpec as SPEC; + $e + } + CustomOpcodeSpecId::SPURIOUS_DRAGON => { + use SpuriousDragonSpec as SPEC; + $e + } + CustomOpcodeSpecId::BYZANTIUM => { + use ByzantiumSpec as SPEC; + $e + } + CustomOpcodeSpecId::PETERSBURG | CustomOpcodeSpecId::CONSTANTINOPLE => { + use PetersburgSpec as SPEC; + $e + } + CustomOpcodeSpecId::ISTANBUL | CustomOpcodeSpecId::MUIR_GLACIER => { + use IstanbulSpec as SPEC; + $e + } + CustomOpcodeSpecId::BERLIN => { + use BerlinSpec as SPEC; + $e + } + CustomOpcodeSpecId::LONDON + | CustomOpcodeSpecId::ARROW_GLACIER + | CustomOpcodeSpecId::GRAY_GLACIER => { + use LondonSpec as SPEC; + $e + } + CustomOpcodeSpecId::MERGE => { + use MergeSpec as SPEC; + $e + } + CustomOpcodeSpecId::SHANGHAI => { + use ShanghaiSpec as SPEC; + $e + } + CustomOpcodeSpecId::CANCUN => { + use CancunSpec as SPEC; + $e + } + CustomOpcodeSpecId::LATEST => { + use LatestSpec as SPEC; + $e + } + CustomOpcodeSpecId::PRAGUE => { + use PragueSpec as SPEC; + $e + } + CustomOpcodeSpecId::INTRODUCES_OPCODE => { + use IntroducesOpcodeSpec as SPEC; + $e + } + } + }}; +} + +impl EvmHandler<'_, CustomOpcodeChainSpec, EXT, DB> { + pub fn custom_opcode_with_spec(spec_id: CustomOpcodeSpecId) -> Self { + let mut handler = Self::mainnet_with_spec(spec_id); + + custom_opcode_spec_to_generic!(spec_id, { + let table = make_custom_instruction_table::<_, SPEC>(); + handler.set_instruction_table(InstructionTables::Plain(table)); + }); + + handler + } +} + +fn make_custom_instruction_table< + ChainSpecT: ChainSpec, + H: Host + ?Sized, + SPEC: CustomOpcodeSpec, +>() -> InstructionTable { + // custom opcode chain can reuse mainnet instructions + let mut table = make_instruction_table::(); + + table[0x0c] = custom_opcode_handler::; + + table +} + +fn custom_opcode_handler< + ChainSpecT: ChainSpec, + H: Host + ?Sized, + SPEC: CustomOpcodeSpec, +>( + interpreter: &mut Interpreter, + _host: &mut H, +) { + // opcode has access to the chain-specific spec + if SPEC::optimism_enabled(CustomOpcodeSpecId::INTRODUCES_OPCODE) { + gas!(interpreter, gas::MID); + } else { + gas!(interpreter, gas::HIGH); + } + + // logic +} diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index a35b807736..7f30d6cb23 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -1,15 +1,15 @@ +use revm_interpreter::Host as _; + use crate::{ builder::{EvmBuilder, HandlerStage, SetGenericStage}, db::{Database, DatabaseCommit, EmptyDB}, - handler::Handler, - interpreter::{ - CallInputs, CreateInputs, EOFCreateInputs, Host, InterpreterAction, SharedMemory, - }, + handler::{EnvWithChainSpec, Handler}, + interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - specification::SpecId, BlockEnv, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, - ExecutionResult, HandlerCfg, ResultAndState, TxEnv, TxKind, EOF_MAGIC_BYTES, + CfgEnv, ChainSpec, EVMError, EVMResult, EthChainSpec, ExecutionResult, ResultAndState, + SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, }, - Context, ContextWithHandlerCfg, Frame, FrameOrResult, FrameResult, + Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, }; use core::fmt; use std::{boxed::Box, vec::Vec}; @@ -19,16 +19,17 @@ pub const CALL_STACK_LIMIT: u64 = 1024; /// EVM instance containing both internal EVM context and external context /// and the handler that dictates the logic of EVM (or hardfork specification). -pub struct Evm<'a, EXT, DB: Database> { +pub struct Evm<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { /// Context of execution, containing both EVM and external context. - pub context: Context, + pub context: Context, /// Handler is a component of the of EVM that contains all the logic. Handler contains specification id /// and it different depending on the specified fork. - pub handler: Handler<'a, Context, EXT, DB>, + pub handler: Handler<'a, ChainSpecT, Context, EXT, DB>, } -impl fmt::Debug for Evm<'_, EXT, DB> +impl fmt::Debug for Evm<'_, ChainSpecT, EXT, DB> where + ChainSpecT: ChainSpec, EXT: fmt::Debug, DB: Database + fmt::Debug, DB::Error: fmt::Debug, @@ -40,41 +41,49 @@ where } } -impl Evm<'_, EXT, DB> { +impl Evm<'_, ChainSpecT, EXT, DB> { /// Commit the changes to the database. - pub fn transact_commit(&mut self) -> Result> { + pub fn transact_commit( + &mut self, + ) -> Result, EVMError> { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) } } -impl<'a> Evm<'a, (), EmptyDB> { - /// Returns evm builder with empty database and empty external context. - pub fn builder() -> EvmBuilder<'a, SetGenericStage, (), EmptyDB> { +impl<'a> Evm<'a, EthChainSpec, (), EmptyDB> { + /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. + pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthChainSpec, (), EmptyDB> { EvmBuilder::default() } } -impl<'a, EXT, DB: Database> Evm<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> { /// Create new EVM. pub fn new( - mut context: Context, - handler: Handler<'a, Context, EXT, DB>, - ) -> Evm<'a, EXT, DB> { - context.evm.journaled_state.set_spec_id(handler.cfg.spec_id); + mut context: Context, + handler: Handler<'a, ChainSpecT, Context, EXT, DB>, + ) -> Evm<'a, ChainSpecT, EXT, DB> { + context + .evm + .journaled_state + .set_spec_id(handler.spec_id.into()); Evm { context, handler } } /// Allow for evm setting to be modified by feeding current evm /// into the builder for modifications. - pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + pub fn modify(self) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { EvmBuilder::new(self) } /// Runs main call loop. #[inline] - pub fn run_the_loop(&mut self, first_frame: Frame) -> Result> { + pub fn run_the_loop( + &mut self, + first_frame: Frame, + ) -> Result> { let mut call_stack: Vec = Vec::with_capacity(1025); call_stack.push(first_frame); @@ -97,7 +106,7 @@ impl<'a, EXT, DB: Database> Evm<'a, EXT, DB> { // Take error and break the loop, if any. // This error can be set in the Interpreter when it interacts with the context. - self.context.evm.take_error()?; + self.context.evm.take_error().map_err(EVMError::Database)?; let exec = &mut self.handler.execution; let frame_or_result = match next_action { @@ -168,18 +177,18 @@ impl<'a, EXT, DB: Database> Evm<'a, EXT, DB> { } } -impl Evm<'_, EXT, DB> { +impl Evm<'_, ChainSpecT, EXT, DB> { /// Returns specification (hardfork) that the EVM is instanced with. /// /// SpecId depends on the handler. - pub fn spec_id(&self) -> SpecId { - self.handler.cfg.spec_id + pub fn spec_id(&self) -> ChainSpecT::Hardfork { + self.handler.spec_id } /// Pre verify transaction by checking Environment, initial gas spend and if caller /// has enough balance to pay for the gas. #[inline] - pub fn preverify_transaction(&mut self) -> Result<(), EVMError> { + pub fn preverify_transaction(&mut self) -> Result<(), EVMError> { let output = self.preverify_transaction_inner().map(|_| ()); self.clear(); output @@ -194,7 +203,7 @@ impl Evm<'_, EXT, DB> { /// /// This function will not validate the transaction. #[inline] - pub fn transact_preverified(&mut self) -> EVMResult { + pub fn transact_preverified(&mut self) -> EVMResult { let initial_gas_spend = self .handler .validation() @@ -211,7 +220,7 @@ impl Evm<'_, EXT, DB> { /// Pre verify transaction inner. #[inline] - fn preverify_transaction_inner(&mut self) -> Result> { + fn preverify_transaction_inner(&mut self) -> Result> { self.handler.validation().env(&self.context.evm.env)?; let initial_gas_spend = self .handler @@ -227,7 +236,7 @@ impl Evm<'_, EXT, DB> { /// /// This function will validate the transaction. #[inline] - pub fn transact(&mut self) -> EVMResult { + pub fn transact(&mut self) -> EVMResult { let initial_gas_spend = self.preverify_transaction_inner().map_err(|e| { self.clear(); e @@ -239,12 +248,6 @@ impl Evm<'_, EXT, DB> { output } - /// Returns the reference of handler configuration - #[inline] - pub fn handler_cfg(&self) -> &HandlerCfg { - &self.handler.cfg - } - /// Returns the reference of Env configuration #[inline] pub fn cfg(&self) -> &CfgEnv { @@ -259,13 +262,13 @@ impl Evm<'_, EXT, DB> { /// Returns the reference of transaction #[inline] - pub fn tx(&self) -> &TxEnv { + pub fn tx(&self) -> &ChainSpecT::Transaction { &self.context.evm.env.tx } /// Returns the mutable reference of transaction #[inline] - pub fn tx_mut(&mut self) -> &mut TxEnv { + pub fn tx_mut(&mut self) -> &mut ChainSpecT::Transaction { &mut self.context.evm.env.tx } @@ -283,47 +286,45 @@ impl Evm<'_, EXT, DB> { /// Returns the reference of block #[inline] - pub fn block(&self) -> &BlockEnv { + pub fn block(&self) -> &ChainSpecT::Block { &self.context.evm.env.block } /// Returns the mutable reference of block #[inline] - pub fn block_mut(&mut self) -> &mut BlockEnv { + pub fn block_mut(&mut self) -> &mut ChainSpecT::Block { &mut self.context.evm.env.block } - /// Modify spec id, this will create new EVM that matches this spec id. - pub fn modify_spec_id(&mut self, spec_id: SpecId) { - self.handler.modify_spec_id(spec_id); - } - /// Returns internal database and external struct. #[inline] - pub fn into_context(self) -> Context { + pub fn into_context(self) -> Context { self.context } - /// Returns database and [`EnvWithHandlerCfg`]. + /// Returns database and [`EnvWithChainSpec`]. #[inline] - pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithHandlerCfg) { + pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithChainSpec) { ( self.context.evm.inner.db, - EnvWithHandlerCfg { + EnvWithChainSpec { env: self.context.evm.inner.env, - handler_cfg: self.handler.cfg, + spec_id: self.handler.spec_id, }, ) } - /// Returns [Context] and [HandlerCfg]. + /// Returns [Context] and hardfork. #[inline] - pub fn into_context_with_handler_cfg(self) -> ContextWithHandlerCfg { - ContextWithHandlerCfg::new(self.context, self.handler.cfg) + pub fn into_context_with_spec_id(self) -> ContextWithChainSpec { + ContextWithChainSpec::new(self.context, self.handler.spec_id) } /// Transact pre-verified transaction. - fn transact_preverified_inner(&mut self, initial_gas_spend: u64) -> EVMResult { + fn transact_preverified_inner( + &mut self, + initial_gas_spend: u64, + ) -> EVMResult { let spec_id = self.spec_id(); let ctx = &mut self.context; let pre_exec = self.handler.pre_execution(); @@ -338,23 +339,26 @@ impl Evm<'_, EXT, DB> { // deduce caller balance with its limit. pre_exec.deduct_caller(ctx)?; - let gas_limit = ctx.evm.env.tx.gas_limit - initial_gas_spend; + let gas_limit = ctx.evm.env.tx.gas_limit() - initial_gas_spend; let exec = self.handler.execution(); // call inner handling of call/create - let first_frame_or_result = match ctx.evm.env.tx.transact_to { + let first_frame_or_result = match ctx.evm.env.tx.transact_to() { TxKind::Call(_) => exec.call( ctx, CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), )?, TxKind::Create => { // if first byte of data is magic 0xEF00, then it is EOFCreate. - if spec_id.is_enabled_in(SpecId::PRAGUE_EOF) - && ctx.env().tx.data.starts_with(&EOF_MAGIC_BYTES) + if Into::::into(spec_id).is_enabled_in(SpecId::PRAGUE_EOF) + && ctx.env().tx.data().starts_with(&EOF_MAGIC_BYTES) { exec.eofcreate( ctx, - Box::new(EOFCreateInputs::new_tx(&ctx.evm.env.tx, gas_limit)), + Box::new(EOFCreateInputs::new_tx::( + &ctx.evm.env.tx, + gas_limit, + )), )? } else { // Safe to unwrap because we are sure that it is create tx. diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 50942fa729..d1e9c7f253 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -1,15 +1,17 @@ // Modules. +pub mod cfg; mod handle_types; pub mod mainnet; pub mod register; // Exports. +pub use cfg::{CfgEnvWithChainSpec, EnvWithChainSpec}; pub use handle_types::*; // Includes. use crate::{ interpreter::{opcode::InstructionTables, Host, InterpreterAction, SharedMemory}, - primitives::{db::Database, spec_to_generic, EVMError, HandlerCfg, Spec, SpecId}, + primitives::{db::Database, spec_to_generic, ChainSpec, EVMError}, Context, Frame, }; use core::mem; @@ -21,91 +23,43 @@ use self::register::{HandleRegister, HandleRegisterBox}; /// Handler acts as a proxy and allow to define different behavior for different /// sections of the code. This allows nice integration of different chains or /// to disable some mainnet behavior. -pub struct Handler<'a, H: Host + 'a, EXT, DB: Database> { - /// Handler configuration. - pub cfg: HandlerCfg, +pub struct Handler<'a, ChainSpecT: ChainSpec, H: Host + 'a, EXT, DB: Database> { + /// Handler hardfork + pub spec_id: ChainSpecT::Hardfork, /// Instruction table type. pub instruction_table: InstructionTables<'a, H>, /// Registers that will be called on initialization. - pub registers: Vec>, + pub registers: Vec>, /// Validity handles. - pub validation: ValidationHandler<'a, EXT, DB>, + pub validation: ValidationHandler<'a, ChainSpecT, EXT, DB>, /// Pre execution handle. - pub pre_execution: PreExecutionHandler<'a, EXT, DB>, + pub pre_execution: PreExecutionHandler<'a, ChainSpecT, EXT, DB>, /// Post Execution handle. - pub post_execution: PostExecutionHandler<'a, EXT, DB>, + pub post_execution: PostExecutionHandler<'a, ChainSpecT, EXT, DB>, /// Execution loop that handles frames. - pub execution: ExecutionHandler<'a, EXT, DB>, + pub execution: ExecutionHandler<'a, ChainSpecT, EXT, DB>, } -impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { - /// Created new Handler with given configuration. - /// - /// Internally it calls `mainnet_with_spec` with the given spec id. - /// Or `optimism_with_spec` if the optimism feature is enabled and `cfg.is_optimism` is set. - pub fn new(cfg: HandlerCfg) -> Self { - cfg_if::cfg_if! { - if #[cfg(feature = "optimism")] { - if cfg.is_optimism { - Handler::optimism_with_spec(cfg.spec_id) - } else { - Handler::mainnet_with_spec(cfg.spec_id) - } - } else { - Handler::mainnet_with_spec(cfg.spec_id) +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EXT, DB> { + /// Creates a base/vanilla Ethereum handler with the provided spec id. + pub fn mainnet_with_spec(spec_id: ChainSpecT::Hardfork) -> Self { + spec_to_generic!( + spec_id.into(), + Self { + spec_id, + instruction_table: InstructionTables::new_plain::(), + registers: Vec::new(), + validation: ValidationHandler::new::(), + pre_execution: PreExecutionHandler::new::(), + post_execution: PostExecutionHandler::mainnet::(), + execution: ExecutionHandler::new::(), } - } - } - - /// Default handler for Ethereum mainnet. - pub fn mainnet() -> Self { - Self { - cfg: HandlerCfg::new(SPEC::SPEC_ID), - instruction_table: InstructionTables::new_plain::(), - registers: Vec::new(), - validation: ValidationHandler::new::(), - pre_execution: PreExecutionHandler::new::(), - post_execution: PostExecutionHandler::new::(), - execution: ExecutionHandler::new::(), - } - } - - /// Returns `true` if the optimism feature is enabled and flag is set to `true`. - pub fn is_optimism(&self) -> bool { - self.cfg.is_optimism() - } - - /// Handler for optimism - #[cfg(feature = "optimism")] - pub fn optimism() -> Self { - let mut handler = Self::mainnet::(); - handler.cfg.is_optimism = true; - handler.append_handler_register(HandleRegisters::Plain( - crate::optimism::optimism_handle_register::, - )); - handler - } - - /// Optimism with spec. Similar to [`Self::mainnet_with_spec`]. - #[cfg(feature = "optimism")] - pub fn optimism_with_spec(spec_id: SpecId) -> Self { - spec_to_generic!(spec_id, Self::optimism::()) - } - - /// Creates handler with variable spec id, inside it will call `mainnet::` for - /// appropriate spec. - pub fn mainnet_with_spec(spec_id: SpecId) -> Self { - spec_to_generic!(spec_id, Self::mainnet::()) - } - - /// Specification ID. - pub fn cfg(&self) -> HandlerCfg { - self.cfg + ) } - /// Returns specification ID. - pub fn spec_id(&self) -> SpecId { - self.cfg.spec_id + /// Returns the specification ID. + pub fn spec_id(&self) -> ChainSpecT::Hardfork { + self.spec_id } /// Executes call frame. @@ -113,71 +67,81 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { &self, frame: &mut Frame, shared_memory: &mut SharedMemory, - context: &mut Context, - ) -> Result> { + context: &mut Context, + ) -> Result> { self.execution .execute_frame(frame, shared_memory, &self.instruction_table, context) } /// Take instruction table. - pub fn take_instruction_table(&mut self) -> InstructionTables<'a, Context> { + pub fn take_instruction_table( + &mut self, + ) -> InstructionTables<'a, Context> { let spec_id = self.spec_id(); mem::replace( &mut self.instruction_table, - spec_to_generic!(spec_id, InstructionTables::new_plain::()), + spec_to_generic!(spec_id.into(), InstructionTables::new_plain::()), ) } /// Set instruction table. - pub fn set_instruction_table(&mut self, table: InstructionTables<'a, Context>) { + pub fn set_instruction_table( + &mut self, + table: InstructionTables<'a, Context>, + ) { self.instruction_table = table; } /// Returns reference to pre execution handler. - pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EXT, DB> { + pub fn pre_execution(&self) -> &PreExecutionHandler<'a, ChainSpecT, EXT, DB> { &self.pre_execution } /// Returns reference to pre execution handler. - pub fn post_execution(&self) -> &PostExecutionHandler<'a, EXT, DB> { + pub fn post_execution(&self) -> &PostExecutionHandler<'a, ChainSpecT, EXT, DB> { &self.post_execution } /// Returns reference to frame handler. - pub fn execution(&self) -> &ExecutionHandler<'a, EXT, DB> { + pub fn execution(&self) -> &ExecutionHandler<'a, ChainSpecT, EXT, DB> { &self.execution } /// Returns reference to validation handler. - pub fn validation(&self) -> &ValidationHandler<'a, EXT, DB> { + pub fn validation(&self) -> &ValidationHandler<'a, ChainSpecT, EXT, DB> { &self.validation } /// Append handle register. - pub fn append_handler_register(&mut self, register: HandleRegisters<'a, EXT, DB>) { + pub fn append_handler_register(&mut self, register: HandleRegisters<'a, ChainSpecT, EXT, DB>) { register.register(self); self.registers.push(register); } /// Append plain handle register. - pub fn append_handler_register_plain(&mut self, register: HandleRegister) { + pub fn append_handler_register_plain(&mut self, register: HandleRegister) { register(self); self.registers.push(HandleRegisters::Plain(register)); } /// Append boxed handle register. - pub fn append_handler_register_box(&mut self, register: HandleRegisterBox<'a, EXT, DB>) { + pub fn append_handler_register_box( + &mut self, + register: HandleRegisterBox<'a, ChainSpecT, EXT, DB>, + ) { register(self); self.registers.push(HandleRegisters::Box(register)); } +} +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EXT, DB> { /// Pop last handle register and reapply all registers that are left. - pub fn pop_handle_register(&mut self) -> Option> { + pub fn pop_handle_register(&mut self) -> Option> { let out = self.registers.pop(); if out.is_some() { let registers = core::mem::take(&mut self.registers); - let mut base_handler = Handler::mainnet_with_spec(self.cfg.spec_id); - // apply all registers to default handeler and raw mainnet instruction table. + let mut base_handler = Handler::mainnet_with_spec(self.spec_id); + // apply all registers to default handler and raw mainnet instruction table. for register in registers { base_handler.append_handler_register(register) } @@ -186,20 +150,9 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { out } - /// Creates the Handler with Generic Spec. - pub fn create_handle_generic(&mut self) -> EvmHandler<'a, EXT, DB> { - let registers = core::mem::take(&mut self.registers); - let mut base_handler = Handler::mainnet::(); - // apply all registers to default handeler and raw mainnet instruction table. - for register in registers { - base_handler.append_handler_register(register) - } - base_handler - } - /// Creates the Handler with variable SpecId, inside it will call function with Generic Spec. - pub fn modify_spec_id(&mut self, spec_id: SpecId) { - if self.cfg.spec_id == spec_id { + pub fn modify_spec_id(&mut self, spec_id: ChainSpecT::Hardfork) { + if self.spec_id == spec_id { return; } @@ -210,8 +163,7 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { for register in registers { handler.append_handler_register(register) } - handler.cfg = self.cfg(); - handler.cfg.spec_id = spec_id; + handler.spec_id = spec_id; *self = handler; } } @@ -225,17 +177,26 @@ mod test { use super::*; + #[cfg(feature = "optimism")] + type TestChainSpec = crate::optimism::OptimismChainSpec; + #[cfg(not(feature = "optimism"))] + type TestChainSpec = crate::primitives::EthChainSpec; + #[test] fn test_handler_register_pop() { - let register = |inner: &Rc>| -> HandleRegisterBox<'_, (), EmptyDB> { - let inner = inner.clone(); - Box::new(move |h| { - *inner.borrow_mut() += 1; - h.post_execution.output = Arc::new(|_, _| Err(EVMError::Custom("test".to_string()))) - }) - }; - - let mut handler = EvmHandler::<(), EmptyDB>::new(HandlerCfg::new(SpecId::LATEST)); + let register = + |inner: &Rc>| -> HandleRegisterBox<'_, TestChainSpec, (), EmptyDB> { + let inner = inner.clone(); + Box::new(move |h| { + *inner.borrow_mut() += 1; + h.post_execution.output = + Arc::new(|_, _| Err(EVMError::Custom("test".to_string()))) + }) + }; + + let mut handler = EvmHandler::<'_, TestChainSpec, (), EmptyDB>::mainnet_with_spec( + ::Hardfork::default(), + ); let test = Rc::new(RefCell::new(0)); handler.append_handler_register_box(register(&test)); diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs new file mode 100644 index 0000000000..cf613ac4f7 --- /dev/null +++ b/crates/revm/src/handler/cfg.rs @@ -0,0 +1,78 @@ +use core::ops::{Deref, DerefMut}; +use std::boxed::Box; + +use crate::primitives::{CfgEnv, ChainSpec, Env}; + +/// Configuration environment with the chain spec id. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CfgEnvWithChainSpec { + /// Configuration environment. + pub cfg_env: CfgEnv, + /// Handler configuration fields. + pub spec_id: ChainSpecT::Hardfork, +} + +impl CfgEnvWithChainSpec { + /// Returns new instance of `CfgEnvWithHandlerCfg`. + pub fn new(cfg_env: CfgEnv, spec_id: ChainSpecT::Hardfork) -> Self { + Self { cfg_env, spec_id } + } +} + +impl DerefMut for CfgEnvWithChainSpec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.cfg_env + } +} + +impl Deref for CfgEnvWithChainSpec { + type Target = CfgEnv; + + fn deref(&self) -> &Self::Target { + &self.cfg_env + } +} + +/// Evm environment with the chain spec id. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct EnvWithChainSpec { + /// Evm enironment. + pub env: Box>, + /// Handler configuration fields. + pub spec_id: ChainSpecT::Hardfork, +} + +impl EnvWithChainSpec { + /// Returns new `EnvWithHandlerCfg` instance. + pub fn new(env: Box>, spec_id: ChainSpecT::Hardfork) -> Self { + Self { env, spec_id } + } + + /// Takes `CfgEnvWithHandlerCfg` and returns new `EnvWithHandlerCfg` instance. + pub fn new_with_cfg_env( + cfg: CfgEnvWithChainSpec, + block: ChainSpecT::Block, + tx: ChainSpecT::Transaction, + ) -> Self { + Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.spec_id) + } + + /// Returns the specification id. + pub const fn spec_id(&self) -> ChainSpecT::Hardfork { + self.spec_id + } +} + +impl DerefMut for EnvWithChainSpec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.env + } +} + +impl Deref for EnvWithChainSpec { + type Target = Env; + + fn deref(&self) -> &Self::Target { + &self.env + } +} diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index 27d31eb118..238b2a8542 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -2,7 +2,7 @@ use crate::{ frame::EOFCreateFrame, handler::mainnet, interpreter::{CallInputs, CreateInputs, SharedMemory}, - primitives::{db::Database, EVMError, Spec}, + primitives::{db::Database, ChainSpec, EVMError, Spec}, CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ @@ -12,166 +12,171 @@ use revm_interpreter::{ use std::{boxed::Box, sync::Arc}; /// Handles first frame return handle. -pub type LastFrameReturnHandle<'a, EXT, DB> = Arc< - dyn Fn(&mut Context, &mut FrameResult) -> Result<(), EVMError<::Error>> +pub type LastFrameReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< + dyn Fn( + &mut Context, + &mut FrameResult, + ) -> Result<(), EVMError::Error>> + 'a, >; /// Executes a single frame. Errors can be returned in the EVM context. -pub type ExecuteFrameHandle<'a, EXT, DB> = Arc< +pub type ExecuteFrameHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Frame, &mut SharedMemory, - &InstructionTables<'_, Context>, - &mut Context, - ) -> Result::Error>> + &InstructionTables<'_, Context>, + &mut Context, + ) -> Result::Error>> + 'a, >; /// Handle sub call. -pub type FrameCallHandle<'a, EXT, DB> = Arc< +pub type FrameCallHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; /// Handle call return -pub type FrameCallReturnHandle<'a, EXT, DB> = Arc< +pub type FrameCallReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; /// Insert call outcome to the parent -pub type InsertCallOutcomeHandle<'a, EXT, DB> = Arc< +pub type InsertCallOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, &mut SharedMemory, CallOutcome, - ) -> Result<(), EVMError<::Error>> + ) -> Result<(), EVMError::Error>> + 'a, >; /// Handle sub create. -pub type FrameCreateHandle<'a, EXT, DB> = Arc< +pub type FrameCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; /// Handle create return -pub type FrameCreateReturnHandle<'a, EXT, DB> = Arc< +pub type FrameCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; /// Insert call outcome to the parent -pub type InsertCreateOutcomeHandle<'a, EXT, DB> = Arc< +pub type InsertCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, CreateOutcome, - ) -> Result<(), EVMError<::Error>> + ) -> Result<(), EVMError::Error>> + 'a, >; /// Handle EOF sub create. -pub type FrameEOFCreateHandle<'a, EXT, DB> = Arc< +pub type FrameEOFCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; /// Handle EOF create return -pub type FrameEOFCreateReturnHandle<'a, EXT, DB> = Arc< +pub type FrameEOFCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; /// Insert EOF crate outcome to the parent -pub type InsertEOFCreateOutcomeHandle<'a, EXT, DB> = Arc< +pub type InsertEOFCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, CreateOutcome, - ) -> Result<(), EVMError<::Error>> + ) -> Result<(), EVMError::Error>> + 'a, >; /// Handles related to stack frames. -pub struct ExecutionHandler<'a, EXT, DB: Database> { +pub struct ExecutionHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { /// Handles last frame return, modified gas for refund and /// sets tx gas limit. - pub last_frame_return: LastFrameReturnHandle<'a, EXT, DB>, + pub last_frame_return: LastFrameReturnHandle<'a, ChainSpecT, EXT, DB>, /// Executes a single frame. - pub execute_frame: ExecuteFrameHandle<'a, EXT, DB>, + pub execute_frame: ExecuteFrameHandle<'a, ChainSpecT, EXT, DB>, /// Frame call - pub call: FrameCallHandle<'a, EXT, DB>, + pub call: FrameCallHandle<'a, ChainSpecT, EXT, DB>, /// Call return - pub call_return: FrameCallReturnHandle<'a, EXT, DB>, + pub call_return: FrameCallReturnHandle<'a, ChainSpecT, EXT, DB>, /// Insert call outcome - pub insert_call_outcome: InsertCallOutcomeHandle<'a, EXT, DB>, + pub insert_call_outcome: InsertCallOutcomeHandle<'a, ChainSpecT, EXT, DB>, /// Frame crate - pub create: FrameCreateHandle<'a, EXT, DB>, + pub create: FrameCreateHandle<'a, ChainSpecT, EXT, DB>, /// Crate return - pub create_return: FrameCreateReturnHandle<'a, EXT, DB>, + pub create_return: FrameCreateReturnHandle<'a, ChainSpecT, EXT, DB>, /// Insert create outcome. - pub insert_create_outcome: InsertCreateOutcomeHandle<'a, EXT, DB>, + pub insert_create_outcome: InsertCreateOutcomeHandle<'a, ChainSpecT, EXT, DB>, /// Frame EOFCreate - pub eofcreate: FrameEOFCreateHandle<'a, EXT, DB>, + pub eofcreate: FrameEOFCreateHandle<'a, ChainSpecT, EXT, DB>, /// EOFCreate return - pub eofcreate_return: FrameEOFCreateReturnHandle<'a, EXT, DB>, + pub eofcreate_return: FrameEOFCreateReturnHandle<'a, ChainSpecT, EXT, DB>, /// Insert EOFCreate outcome. - pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, EXT, DB>, + pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, ChainSpecT, EXT, DB>, } -impl<'a, EXT: 'a, DB: Database + 'a> ExecutionHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> + ExecutionHandler<'a, ChainSpecT, EXT, DB> +{ /// Creates mainnet ExecutionHandler. pub fn new() -> Self { Self { - last_frame_return: Arc::new(mainnet::last_frame_return::), - execute_frame: Arc::new(mainnet::execute_frame::), - call: Arc::new(mainnet::call::), - call_return: Arc::new(mainnet::call_return::), + last_frame_return: Arc::new(mainnet::last_frame_return::), + execute_frame: Arc::new(mainnet::execute_frame::), + call: Arc::new(mainnet::call::), + call_return: Arc::new(mainnet::call_return::), insert_call_outcome: Arc::new(mainnet::insert_call_outcome), - create: Arc::new(mainnet::create::), - create_return: Arc::new(mainnet::create_return::), + create: Arc::new(mainnet::create::), + create_return: Arc::new(mainnet::create_return::), insert_create_outcome: Arc::new(mainnet::insert_create_outcome), - eofcreate: Arc::new(mainnet::eofcreate::), - eofcreate_return: Arc::new(mainnet::eofcreate_return::), + eofcreate: Arc::new(mainnet::eofcreate::), + eofcreate_return: Arc::new(mainnet::eofcreate_return::), insert_eofcreate_outcome: Arc::new(mainnet::insert_eofcreate_outcome), } } } -impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpecT, EXT, DB> { /// Executes single frame. #[inline] pub fn execute_frame( &self, frame: &mut Frame, shared_memory: &mut SharedMemory, - instruction_tables: &InstructionTables<'_, Context>, - context: &mut Context, - ) -> Result> { + instruction_tables: &InstructionTables<'_, Context>, + context: &mut Context, + ) -> Result> { (self.execute_frame)(frame, shared_memory, instruction_tables, context) } @@ -179,9 +184,9 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn last_frame_return( &self, - context: &mut Context, + context: &mut Context, frame_result: &mut FrameResult, - ) -> Result<(), EVMError> { + ) -> Result<(), EVMError> { (self.last_frame_return)(context, frame_result) } @@ -189,9 +194,9 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn call( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> Result> { + ) -> Result> { (self.call)(context, inputs) } @@ -199,10 +204,10 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn call_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result> { (self.call_return)(context, frame, interpreter_result) } @@ -210,11 +215,11 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn insert_call_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, - ) -> Result<(), EVMError> { + ) -> Result<(), EVMError> { (self.insert_call_outcome)(context, frame, shared_memory, outcome) } @@ -222,9 +227,9 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn create( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> Result> { + ) -> Result> { (self.create)(context, inputs) } @@ -232,10 +237,10 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn create_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result> { (self.create_return)(context, frame, interpreter_result) } @@ -243,10 +248,10 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn insert_create_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> Result<(), EVMError> { + ) -> Result<(), EVMError> { (self.insert_create_outcome)(context, frame, outcome) } @@ -254,9 +259,9 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn eofcreate( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> Result> { + ) -> Result> { (self.eofcreate)(context, inputs) } @@ -264,10 +269,10 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn eofcreate_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result> { (self.eofcreate_return)(context, frame, interpreter_result) } @@ -275,10 +280,10 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { #[inline] pub fn insert_eofcreate_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> Result<(), EVMError> { + ) -> Result<(), EVMError> { (self.insert_eofcreate_outcome)(context, frame, outcome) } } diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index bfe9aab695..dcf5cb72ca 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -2,24 +2,31 @@ use crate::{ handler::mainnet, interpreter::Gas, - primitives::{db::Database, EVMError, EVMResultGeneric, ResultAndState, Spec}, + primitives::{db::Database, ChainSpec, EVMError, EVMResultGeneric, ResultAndState, Spec}, Context, FrameResult, }; use std::sync::Arc; /// Reimburse the caller with ethereum it didn't spent. -pub type ReimburseCallerHandle<'a, EXT, DB> = - Arc, &Gas) -> EVMResultGeneric<(), ::Error> + 'a>; +pub type ReimburseCallerHandle<'a, ChainSpecT, EXT, DB> = Arc< + dyn Fn( + &mut Context, + &Gas, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, +>; /// Reward beneficiary with transaction rewards. -pub type RewardBeneficiaryHandle<'a, EXT, DB> = ReimburseCallerHandle<'a, EXT, DB>; +pub type RewardBeneficiaryHandle<'a, ChainSpecT, EXT, DB> = + ReimburseCallerHandle<'a, ChainSpecT, EXT, DB>; /// Main return handle, takes state from journal and transforms internal result to external. -pub type OutputHandle<'a, EXT, DB> = Arc< +pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, FrameResult, - ) -> Result::Error>> + ) + -> Result, EVMError::Error>> + 'a, >; @@ -27,86 +34,89 @@ pub type OutputHandle<'a, EXT, DB> = Arc< /// This will be called after all the other handlers. /// /// It is useful for catching errors and returning them in a different way. -pub type EndHandle<'a, EXT, DB> = Arc< +pub type EndHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( - &mut Context, - Result::Error>>, - ) -> Result::Error>> + &mut Context, + Result, EVMError::Error>>, + ) + -> Result, EVMError::Error>> + 'a, >; /// Clear handle, doesn't have output, its purpose is to clear the /// context. It will always be called even on failed validation. -pub type ClearHandle<'a, EXT, DB> = Arc) + 'a>; +pub type ClearHandle<'a, ChainSpecT, EXT, DB> = Arc) + 'a>; /// Handles related to post execution after the stack loop is finished. -pub struct PostExecutionHandler<'a, EXT, DB: Database> { +pub struct PostExecutionHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { /// Reimburse the caller with ethereum it didn't spend. - pub reimburse_caller: ReimburseCallerHandle<'a, EXT, DB>, + pub reimburse_caller: ReimburseCallerHandle<'a, ChainSpecT, EXT, DB>, /// Reward the beneficiary with caller fee. - pub reward_beneficiary: RewardBeneficiaryHandle<'a, EXT, DB>, + pub reward_beneficiary: RewardBeneficiaryHandle<'a, ChainSpecT, EXT, DB>, /// Main return handle, returns the output of the transact. - pub output: OutputHandle<'a, EXT, DB>, + pub output: OutputHandle<'a, ChainSpecT, EXT, DB>, /// Called when execution ends. /// End handle in comparison to output handle will be called every time after execution. /// Output in case of error will not be called. - pub end: EndHandle<'a, EXT, DB>, + pub end: EndHandle<'a, ChainSpecT, EXT, DB>, /// Clear handle will be called always. In comparison to end that /// is called only on execution end, clear handle is called even if validation fails. - pub clear: ClearHandle<'a, EXT, DB>, + pub clear: ClearHandle<'a, ChainSpecT, EXT, DB>, } -impl<'a, EXT: 'a, DB: Database + 'a> PostExecutionHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> + PostExecutionHandler<'a, ChainSpecT, EXT, DB> +{ /// Creates mainnet MainHandles. - pub fn new() -> Self { + pub fn mainnet() -> Self { Self { - reimburse_caller: Arc::new(mainnet::reimburse_caller::), - reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), - output: Arc::new(mainnet::output::), - end: Arc::new(mainnet::end::), - clear: Arc::new(mainnet::clear::), + reimburse_caller: Arc::new(mainnet::reimburse_caller::), + reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), + output: Arc::new(mainnet::output::), + end: Arc::new(mainnet::end::), + clear: Arc::new(mainnet::clear::), } } } -impl<'a, EXT, DB: Database> PostExecutionHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, ChainSpecT, EXT, DB> { /// Reimburse the caller with gas that were not spend. pub fn reimburse_caller( &self, - context: &mut Context, + context: &mut Context, gas: &Gas, - ) -> Result<(), EVMError> { + ) -> Result<(), EVMError> { (self.reimburse_caller)(context, gas) } /// Reward beneficiary pub fn reward_beneficiary( &self, - context: &mut Context, + context: &mut Context, gas: &Gas, - ) -> Result<(), EVMError> { + ) -> Result<(), EVMError> { (self.reward_beneficiary)(context, gas) } /// Returns the output of transaction. pub fn output( &self, - context: &mut Context, + context: &mut Context, result: FrameResult, - ) -> Result> { + ) -> Result, EVMError> { (self.output)(context, result) } /// End handler. pub fn end( &self, - context: &mut Context, - end_output: Result>, - ) -> Result> { + context: &mut Context, + end_output: Result, EVMError>, + ) -> Result, EVMError> { (self.end)(context, end_output) } /// Clean handler. - pub fn clear(&self, context: &mut Context) { + pub fn clear(&self, context: &mut Context) { (self.clear)(context) } } diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 1956d67f13..baaf3dd677 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -1,58 +1,75 @@ // Includes. use crate::{ handler::mainnet, - primitives::{db::Database, EVMError, EVMResultGeneric, Spec}, + primitives::{db::Database, ChainSpec, EVMError, EVMResultGeneric, Spec}, Context, ContextPrecompiles, }; use std::sync::Arc; /// Loads precompiles into Evm -pub type LoadPrecompilesHandle<'a, DB> = Arc ContextPrecompiles + 'a>; +pub type LoadPrecompilesHandle<'a, ChainSpecT, DB> = + Arc ContextPrecompiles + 'a>; /// Load access list accounts and beneficiary. /// There is no need to load Caller as it is assumed that /// it will be loaded in DeductCallerHandle. -pub type LoadAccountsHandle<'a, EXT, DB> = - Arc) -> Result<(), EVMError<::Error>> + 'a>; +pub type LoadAccountsHandle<'a, ChainSpecT, EXT, DB> = Arc< + dyn Fn( + &mut Context, + ) -> Result<(), EVMError::Error>> + + 'a, +>; /// Deduct the caller to its limit. -pub type DeductCallerHandle<'a, EXT, DB> = - Arc) -> EVMResultGeneric<(), ::Error> + 'a>; +pub type DeductCallerHandle<'a, ChainSpecT, EXT, DB> = Arc< + dyn Fn( + &mut Context, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, +>; /// Handles related to pre execution before the stack loop is started. -pub struct PreExecutionHandler<'a, EXT, DB: Database> { +pub struct PreExecutionHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { /// Load precompiles - pub load_precompiles: LoadPrecompilesHandle<'a, DB>, + pub load_precompiles: LoadPrecompilesHandle<'a, ChainSpecT, DB>, /// Main load handle - pub load_accounts: LoadAccountsHandle<'a, EXT, DB>, + pub load_accounts: LoadAccountsHandle<'a, ChainSpecT, EXT, DB>, /// Deduct max value from the caller. - pub deduct_caller: DeductCallerHandle<'a, EXT, DB>, + pub deduct_caller: DeductCallerHandle<'a, ChainSpecT, EXT, DB>, } -impl<'a, EXT: 'a, DB: Database + 'a> PreExecutionHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> + PreExecutionHandler<'a, ChainSpecT, EXT, DB> +{ /// Creates mainnet MainHandles. pub fn new() -> Self { Self { - load_precompiles: Arc::new(mainnet::load_precompiles::), - load_accounts: Arc::new(mainnet::load_accounts::), - deduct_caller: Arc::new(mainnet::deduct_caller::), + load_precompiles: Arc::new(mainnet::load_precompiles::), + load_accounts: Arc::new(mainnet::load_accounts::), + deduct_caller: Arc::new(mainnet::deduct_caller::), } } } -impl<'a, EXT, DB: Database> PreExecutionHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PreExecutionHandler<'a, ChainSpecT, EXT, DB> { /// Deduct caller to its limit. - pub fn deduct_caller(&self, context: &mut Context) -> Result<(), EVMError> { + pub fn deduct_caller( + &self, + context: &mut Context, + ) -> Result<(), EVMError> { (self.deduct_caller)(context) } /// Main load - pub fn load_accounts(&self, context: &mut Context) -> Result<(), EVMError> { + pub fn load_accounts( + &self, + context: &mut Context, + ) -> Result<(), EVMError> { (self.load_accounts)(context) } /// Load precompiles - pub fn load_precompiles(&self) -> ContextPrecompiles { + pub fn load_precompiles(&self) -> ContextPrecompiles { (self.load_precompiles)() } } diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index 8aa55c28c2..1cc8b2abbb 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -1,60 +1,72 @@ use crate::{ handler::mainnet, - primitives::{db::Database, EVMError, Env, Spec}, + primitives::{db::Database, ChainSpec, EVMError, Env, Spec}, Context, }; use std::sync::Arc; /// Handle that validates env. -pub type ValidateEnvHandle<'a, DB> = - Arc Result<(), EVMError<::Error>> + 'a>; +pub type ValidateEnvHandle<'a, ChainSpecT, DB> = + Arc) -> Result<(), EVMError::Error>> + 'a>; /// Handle that validates transaction environment against the state. /// Second parametar is initial gas. -pub type ValidateTxEnvAgainstState<'a, EXT, DB> = - Arc) -> Result<(), EVMError<::Error>> + 'a>; +pub type ValidateTxEnvAgainstState<'a, ChainSpecT, EXT, DB> = Arc< + dyn Fn( + &mut Context, + ) -> Result<(), EVMError::Error>> + + 'a, +>; /// Initial gas calculation handle -pub type ValidateInitialTxGasHandle<'a, DB> = - Arc Result::Error>> + 'a>; +pub type ValidateInitialTxGasHandle<'a, ChainSpecT, DB> = Arc< + dyn Fn(&Env) -> Result::Error>> + 'a, +>; /// Handles related to validation. -pub struct ValidationHandler<'a, EXT, DB: Database> { +pub struct ValidationHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { /// Validate and calculate initial transaction gas. - pub initial_tx_gas: ValidateInitialTxGasHandle<'a, DB>, + pub initial_tx_gas: ValidateInitialTxGasHandle<'a, ChainSpecT, DB>, /// Validate transactions against state data. - pub tx_against_state: ValidateTxEnvAgainstState<'a, EXT, DB>, + pub tx_against_state: ValidateTxEnvAgainstState<'a, ChainSpecT, EXT, DB>, /// Validate Env. - pub env: ValidateEnvHandle<'a, DB>, + pub env: ValidateEnvHandle<'a, ChainSpecT, DB>, } -impl<'a, EXT: 'a, DB: Database + 'a> ValidationHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> + ValidationHandler<'a, ChainSpecT, EXT, DB> +{ /// Create new ValidationHandles pub fn new() -> Self { Self { - initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), - env: Arc::new(mainnet::validate_env::), - tx_against_state: Arc::new(mainnet::validate_tx_against_state::), + initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), + env: Arc::new(mainnet::validate_env::), + tx_against_state: Arc::new( + mainnet::validate_tx_against_state::, + ), } } } -impl<'a, EXT, DB: Database> ValidationHandler<'a, EXT, DB> { +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSpecT, EXT, DB> { /// Validate env. - pub fn env(&self, env: &Env) -> Result<(), EVMError> { + pub fn env(&self, env: &Env) -> Result<(), EVMError> { (self.env)(env) } /// Initial gas - pub fn initial_tx_gas(&self, env: &Env) -> Result> { + pub fn initial_tx_gas( + &self, + env: &Env, + ) -> Result> { (self.initial_tx_gas)(env) } /// Validate ttansaction against the state. pub fn tx_against_state( &self, - context: &mut Context, - ) -> Result<(), EVMError> { + context: &mut Context, + ) -> Result<(), EVMError> { (self.tx_against_state)(context) } } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 89094d771e..08208fe733 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -5,7 +5,7 @@ use crate::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, SharedMemory, }, - primitives::{EVMError, Env, Spec, SpecId}, + primitives::{ChainSpec, EVMError, Env, Spec, SpecId, Transaction}, CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use core::mem; @@ -17,12 +17,12 @@ use std::boxed::Box; /// Execute frame #[inline] -pub fn execute_frame( +pub fn execute_frame( frame: &mut Frame, shared_memory: &mut SharedMemory, - instruction_tables: &InstructionTables<'_, Context>, - context: &mut Context, -) -> Result> { + instruction_tables: &InstructionTables<'_, Context>, + context: &mut Context, +) -> Result> { let interpreter = frame.interpreter_mut(); let memory = mem::replace(shared_memory, EMPTY_SHARED_MEMORY); let next_action = match instruction_tables { @@ -37,8 +37,8 @@ pub fn execute_frame( /// Helper function called inside [`last_frame_return`] #[inline] -pub fn frame_return_with_refund_flag( - env: &Env, +pub fn frame_return_with_refund_flag( + env: &Env, frame_result: &mut FrameResult, refund_enabled: bool, ) { @@ -48,7 +48,7 @@ pub fn frame_return_with_refund_flag( let refunded = gas.refunded(); // Spend the gas limit. Gas is reimbursed when the tx returns successfully. - *gas = Gas::new_spent(env.tx.gas_limit); + *gas = Gas::new_spent(env.tx.gas_limit()); match instruction_result { return_ok!() => { @@ -73,29 +73,29 @@ pub fn frame_return_with_refund_flag( /// Handle output of the transaction #[inline] -pub fn last_frame_return( - context: &mut Context, +pub fn last_frame_return( + context: &mut Context, frame_result: &mut FrameResult, -) -> Result<(), EVMError> { - frame_return_with_refund_flag::(&context.evm.env, frame_result, true); +) -> Result<(), EVMError> { + frame_return_with_refund_flag::(&context.evm.env, frame_result, true); Ok(()) } /// Handle frame sub call. #[inline] -pub fn call( - context: &mut Context, +pub fn call( + context: &mut Context, inputs: Box, -) -> Result> { +) -> Result> { context.evm.make_call_frame(&inputs) } #[inline] -pub fn call_return( - context: &mut Context, +pub fn call_return( + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, -) -> Result> { +) -> Result> { context .evm .call_return(&interpreter_result, frame.frame_data.checkpoint); @@ -106,13 +106,14 @@ pub fn call_return( } #[inline] -pub fn insert_call_outcome( - context: &mut Context, +pub fn insert_call_outcome( + context: &mut Context, frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, -) -> Result<(), EVMError> { - context.evm.take_error()?; +) -> Result<(), EVMError> { + context.evm.take_error().map_err(EVMError::Database)?; + frame .frame_data_mut() .interpreter @@ -122,19 +123,22 @@ pub fn insert_call_outcome( /// Handle frame sub create. #[inline] -pub fn create( - context: &mut Context, +pub fn create( + context: &mut Context, inputs: Box, -) -> Result> { - context.evm.make_create_frame(SPEC::SPEC_ID, &inputs) +) -> Result> { + context + .evm + .make_create_frame(SPEC::SPEC_ID, &inputs) + .map_err(EVMError::Database) } #[inline] -pub fn create_return( - context: &mut Context, +pub fn create_return( + context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result> { +) -> Result> { context.evm.create_return::( &mut interpreter_result, frame.created_address, @@ -147,12 +151,13 @@ pub fn create_return( } #[inline] -pub fn insert_create_outcome( - context: &mut Context, +pub fn insert_create_outcome( + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> Result<(), EVMError> { - context.evm.take_error()?; +) -> Result<(), EVMError> { + context.evm.take_error().map_err(EVMError::Database)?; + frame .frame_data_mut() .interpreter @@ -162,19 +167,22 @@ pub fn insert_create_outcome( /// Handle frame sub create. #[inline] -pub fn eofcreate( - context: &mut Context, +pub fn eofcreate( + context: &mut Context, inputs: Box, -) -> Result> { - context.evm.make_eofcreate_frame(SPEC::SPEC_ID, &inputs) +) -> Result> { + context + .evm + .make_eofcreate_frame(SPEC::SPEC_ID, &inputs) + .map_err(EVMError::Database) } #[inline] -pub fn eofcreate_return( - context: &mut Context, +pub fn eofcreate_return( + context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result> { +) -> Result> { context.evm.eofcreate_return::( &mut interpreter_result, frame.created_address, @@ -187,12 +195,13 @@ pub fn eofcreate_return( } #[inline] -pub fn insert_eofcreate_outcome( - context: &mut Context, +pub fn insert_eofcreate_outcome( + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> Result<(), EVMError> { - core::mem::replace(&mut context.evm.error, Ok(()))?; +) -> Result<(), EVMError> { + core::mem::replace(&mut context.evm.error, Ok(())).map_err(EVMError::Database)?; + frame .frame_data_mut() .interpreter @@ -203,12 +212,13 @@ pub fn insert_eofcreate_outcome( #[cfg(test)] mod tests { use super::*; + use crate::primitives::EthChainSpec; use revm_interpreter::primitives::CancunSpec; use revm_precompile::Bytes; /// Creates frame result. fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { - let mut env = Env::default(); + let mut env = Env::::default(); env.tx.gas_limit = 100; let mut first_frame = FrameResult::Call(CallOutcome::new( @@ -219,7 +229,7 @@ mod tests { }, 0..0, )); - frame_return_with_refund_flag::(&env, &mut first_frame, true); + frame_return_with_refund_flag::(&env, &mut first_frame, true); *first_frame.gas() } diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index cc5e7bb9bc..e1df54b80c 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,24 +1,24 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, Bytecode, EVMError, ExecutionResult, ResultAndState, Spec, SpecId::LONDON, - KECCAK_EMPTY, U256, + db::Database, Block, Bytecode, ChainSpec, EVMError, ExecutionResult, ResultAndState, Spec, + SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, }, Context, FrameResult, }; /// Mainnet end handle does not change the output. #[inline] -pub fn end( - _context: &mut Context, - evm_output: Result>, -) -> Result> { +pub fn end( + _context: &mut Context, + evm_output: Result, EVMError>, +) -> Result, EVMError> { evm_output } /// Clear handle clears error and journal state. #[inline] -pub fn clear(context: &mut Context) { +pub fn clear(context: &mut Context) { // clear error and journaled state. let _ = context.evm.take_error(); context.evm.inner.journaled_state.clear(); @@ -29,17 +29,17 @@ pub fn clear(context: &mut Context) { /// Reward beneficiary with gas fee. #[inline] -pub fn reward_beneficiary( - context: &mut Context, +pub fn reward_beneficiary( + context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { - let beneficiary = context.evm.env.block.coinbase; +) -> Result<(), EVMError> { + let beneficiary = *context.evm.env.block.coinbase(); let effective_gas_price = context.evm.env.effective_gas_price(); // transfer fee to coinbase/beneficiary. // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. let coinbase_gas_price = if SPEC::enabled(LONDON) { - effective_gas_price.saturating_sub(context.evm.env.block.basefee) + effective_gas_price.saturating_sub(*context.evm.env.block.basefee()) } else { effective_gas_price }; @@ -48,7 +48,8 @@ pub fn reward_beneficiary( .evm .inner .journaled_state - .load_account(beneficiary, &mut context.evm.inner.db)?; + .load_account(beneficiary, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; coinbase_account.mark_touch(); coinbase_account.info.balance = coinbase_account @@ -60,11 +61,11 @@ pub fn reward_beneficiary( } #[inline] -pub fn reimburse_caller( - context: &mut Context, +pub fn reimburse_caller( + context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { - let caller = context.evm.env.tx.caller; +) -> Result<(), EVMError> { + let caller = context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); // return balance of not spend gas. @@ -72,7 +73,8 @@ pub fn reimburse_caller( .evm .inner .journaled_state - .load_account(caller, &mut context.evm.inner.db)?; + .load_account(*caller, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; caller_account.info.balance = caller_account .info @@ -84,11 +86,12 @@ pub fn reimburse_caller( /// Main return handle, returns the output of the transaction. #[inline] -pub fn output( - context: &mut Context, +pub fn output( + context: &mut Context, result: FrameResult, -) -> Result> { - context.evm.take_error()?; +) -> Result, EVMError> { + context.evm.take_error().map_err(EVMError::Database)?; + // used gas with refund calculated. let gas_refunded = result.gas().refunded() as u64; let final_gas_used = result.gas().spent() - gas_refunded; @@ -107,7 +110,7 @@ pub fn output( account.info.code_hash = KECCAK_EMPTY; } - let result = match instruction_result.result.into() { + let result = match SuccessOrHalt::::from(instruction_result.result) { SuccessOrHalt::Success(reason) => ExecutionResult::Success { reason, gas_used: final_gas_used, diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 8d04986de8..da95e91417 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -5,10 +5,8 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ - db::Database, - Account, EVMError, Env, Spec, - SpecId::{CANCUN, PRAGUE, SHANGHAI}, - TxKind, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, + db::Database, Account, Block, ChainSpec, EVMError, Env, Spec, SpecId, Transaction as _, + BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, }; @@ -16,22 +14,23 @@ use std::vec::Vec; /// Main precompile load #[inline] -pub fn load_precompiles() -> ContextPrecompiles { +pub fn load_precompiles( +) -> ContextPrecompiles { ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) } /// Main load handle #[inline] -pub fn load_accounts( - context: &mut Context, -) -> Result<(), EVMError> { +pub fn load_accounts( + context: &mut Context, +) -> Result<(), EVMError> { // set journaling state flag. context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); // load coinbase // EIP-3651: Warm COINBASE. Starts the `COINBASE` address warm - if SPEC::enabled(SHANGHAI) { - let coinbase = context.evm.inner.env.block.coinbase; + if SPEC::enabled(SpecId::SHANGHAI) { + let coinbase = *context.evm.inner.env.block.coinbase(); context .evm .journaled_state @@ -41,7 +40,7 @@ pub fn load_accounts( // Load blockhash storage address // EIP-2935: Serve historical block hashes from state - if SPEC::enabled(PRAGUE) { + if SPEC::enabled(SpecId::PRAGUE) { context .evm .journaled_state @@ -50,8 +49,8 @@ pub fn load_accounts( } // EIP-7702. Load bytecode to authorized accounts. - if SPEC::enabled(PRAGUE) { - if let Some(authorization_list) = context.evm.inner.env.tx.authorization_list.as_ref() { + if SPEC::enabled(SpecId::PRAGUE) { + if let Some(authorization_list) = context.evm.inner.env.tx.authorization_list().as_ref() { let mut valid_auths = Vec::with_capacity(authorization_list.len()); for authorization in authorization_list.recovered_iter() { // 1. recover authority and authorized addresses. @@ -71,7 +70,8 @@ pub fn load_accounts( .evm .inner .journaled_state - .load_account(authority, &mut context.evm.inner.db)?; + .load_account(authority, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; // 3. Verify that the code of authority is empty. // In case of multiple same authorities this step will skip loading of @@ -93,7 +93,9 @@ pub fn load_accounts( .evm .inner .journaled_state - .load_code(authorization.address, &mut context.evm.inner.db)?; + .load_code(authorization.address, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; + let code = account.info.code.clone(); let code_hash = account.info.code_hash; @@ -117,19 +119,22 @@ pub fn load_accounts( } } - context.evm.load_access_list()?; + context.evm.load_access_list().map_err(EVMError::Database)?; Ok(()) } /// Helper function that deducts the caller balance. #[inline] -pub fn deduct_caller_inner(caller_account: &mut Account, env: &Env) { +pub fn deduct_caller_inner( + caller_account: &mut Account, + env: &Env, +) { // Subtract gas costs from the caller's account. // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. - let mut gas_cost = U256::from(env.tx.gas_limit).saturating_mul(env.effective_gas_price()); + let mut gas_cost = U256::from(env.tx.gas_limit()).saturating_mul(env.effective_gas_price()); // EIP-4844 - if SPEC::enabled(CANCUN) { + if SPEC::enabled(SpecId::CANCUN) { let data_fee = env.calc_data_fee().expect("already checked"); gas_cost = gas_cost.saturating_add(data_fee); } @@ -138,7 +143,7 @@ pub fn deduct_caller_inner(caller_account: &mut Account, env: &Env) caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost); // bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. - if matches!(env.tx.transact_to, TxKind::Call(_)) { + if env.tx.transact_to().is_call() { // Nonce is already checked caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } @@ -149,18 +154,22 @@ pub fn deduct_caller_inner(caller_account: &mut Account, env: &Env) /// Deducts the caller balance to the transaction limit. #[inline] -pub fn deduct_caller( - context: &mut Context, -) -> Result<(), EVMError> { +pub fn deduct_caller( + context: &mut Context, +) -> Result<(), EVMError> { // load caller's account. let (caller_account, _) = context .evm .inner .journaled_state - .load_account(context.evm.inner.env.tx.caller, &mut context.evm.inner.db)?; + .load_account( + *context.evm.inner.env.tx.caller(), + &mut context.evm.inner.db, + ) + .map_err(EVMError::Database)?; // deduct gas cost from caller's account. - deduct_caller_inner::(caller_account, &context.evm.inner.env); + deduct_caller_inner::(caller_account, &context.evm.inner.env); Ok(()) } diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index f8840de42c..9ac16adc02 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -1,50 +1,54 @@ use revm_interpreter::gas; use crate::{ - primitives::{db::Database, EVMError, Env, InvalidTransaction, Spec}, + primitives::{db::Database, ChainSpec, EVMError, Env, InvalidTransaction, Spec, Transaction}, Context, }; /// Validate environment for the mainnet. -pub fn validate_env(env: &Env) -> Result<(), EVMError> { +pub fn validate_env( + env: &Env, +) -> Result<(), EVMError> { // Important: validate block before tx. env.validate_block_env::()?; - env.validate_tx::()?; + env.validate_tx::() + .map_err(|error| EVMError::Transaction(error.into()))?; Ok(()) } /// Validates transaction against the state. -pub fn validate_tx_against_state( - context: &mut Context, -) -> Result<(), EVMError> { +pub fn validate_tx_against_state( + context: &mut Context, +) -> Result<(), EVMError> { // load acc - let tx_caller = context.evm.env.tx.caller; + let tx_caller = context.evm.env.tx.caller(); let (caller_account, _) = context .evm .inner .journaled_state - .load_account(tx_caller, &mut context.evm.inner.db)?; + .load_account(*tx_caller, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; context .evm .inner .env .validate_tx_against_state::(caller_account) - .map_err(EVMError::Transaction)?; + .map_err(|error| EVMError::Transaction(error.into()))?; Ok(()) } /// Validate initial transaction gas. -pub fn validate_initial_tx_gas( - env: &Env, -) -> Result> { - let input = &env.tx.data; - let is_create = env.tx.transact_to.is_create(); - let access_list = &env.tx.access_list; +pub fn validate_initial_tx_gas( + env: &Env, +) -> Result> { + let input = &env.tx.data(); + let is_create = env.tx.transact_to().is_create(); + let access_list = &env.tx.access_list(); let authorization_list_num = env .tx - .authorization_list + .authorization_list() .as_ref() .map(|l| l.len() as u64) .unwrap_or_default(); @@ -58,8 +62,10 @@ pub fn validate_initial_tx_gas( ); // Additional check to see if limit is big enough to cover initial gas. - if initial_gas_spend > env.tx.gas_limit { - return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into()); + if initial_gas_spend > env.tx.gas_limit() { + return Err(EVMError::Transaction( + InvalidTransaction::CallGasCostMoreThanGasLimit.into(), + )); } Ok(initial_gas_spend) } diff --git a/crates/revm/src/handler/register.rs b/crates/revm/src/handler/register.rs index e05225c17c..ba1b30620c 100644 --- a/crates/revm/src/handler/register.rs +++ b/crates/revm/src/handler/register.rs @@ -1,25 +1,29 @@ -use crate::{db::Database, handler::Handler, Context}; +use crate::{db::Database, handler::Handler, primitives::ChainSpec, Context}; use std::boxed::Box; /// EVM Handler -pub type EvmHandler<'a, EXT, DB> = Handler<'a, Context, EXT, DB>; +pub type EvmHandler<'a, ChainSpecT, EXT, DB> = + Handler<'a, ChainSpecT, Context, EXT, DB>; // Handle register -pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, EXT, DB>); +pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, ChainSpecT, EXT, DB>); // Boxed handle register -pub type HandleRegisterBox<'a, EXT, DB> = Box Fn(&mut EvmHandler<'e, EXT, DB>) + 'a>; +pub type HandleRegisterBox<'a, ChainSpecT, EXT, DB> = + Box Fn(&mut EvmHandler<'e, ChainSpecT, EXT, DB>) + 'a>; -pub enum HandleRegisters<'a, EXT, DB: Database> { +pub enum HandleRegisters<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { /// Plain function register - Plain(HandleRegister), + Plain(HandleRegister), /// Boxed function register. - Box(HandleRegisterBox<'a, EXT, DB>), + Box(HandleRegisterBox<'a, ChainSpecT, EXT, DB>), } -impl<'register, EXT, DB: Database> HandleRegisters<'register, EXT, DB> { +impl<'register, ChainSpecT: ChainSpec, EXT, DB: Database> + HandleRegisters<'register, ChainSpecT, EXT, DB> +{ /// Call register function to modify EvmHandler. - pub fn register<'evm>(&self, handler: &mut EvmHandler<'evm, EXT, DB>) + pub fn register<'evm>(&self, handler: &mut EvmHandler<'evm, ChainSpecT, EXT, DB>) where 'evm: 'register, { diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 046ec50761..23635ddfb5 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -12,7 +12,7 @@ use crate::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, }, - primitives::{db::Database, Address, Log, U256}, + primitives::{db::Database, Address, ChainSpec, Log, U256}, EvmContext, }; use auto_impl::auto_impl; @@ -29,13 +29,17 @@ pub mod inspectors { /// EVM [Interpreter] callbacks. #[auto_impl(&mut, Box)] -pub trait Inspector { +pub trait Inspector { /// Called before the interpreter is initialized. /// /// If `interp.instruction_result` is set to anything other than [crate::interpreter::InstructionResult::Continue] then the execution of the interpreter /// is skipped. #[inline] - fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn initialize_interp( + &mut self, + interp: &mut Interpreter, + context: &mut EvmContext, + ) { let _ = interp; let _ = context; } @@ -49,7 +53,7 @@ pub trait Inspector { /// /// To get the current opcode, use `interp.current_opcode()`. #[inline] - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let _ = interp; let _ = context; } @@ -59,14 +63,19 @@ pub trait Inspector { /// Setting `interp.instruction_result` to anything other than [crate::interpreter::InstructionResult::Continue] alters the execution /// of the interpreter. #[inline] - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let _ = interp; let _ = context; } /// Called when a log is emitted. #[inline] - fn log(&mut self, interp: &mut Interpreter, context: &mut EvmContext, log: &Log) { + fn log( + &mut self, + interp: &mut Interpreter, + context: &mut EvmContext, + log: &Log, + ) { let _ = interp; let _ = context; let _ = log; @@ -78,7 +87,7 @@ pub trait Inspector { #[inline] fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut CallInputs, ) -> Option { let _ = context; @@ -94,7 +103,7 @@ pub trait Inspector { #[inline] fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -111,7 +120,7 @@ pub trait Inspector { #[inline] fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { let _ = context; @@ -126,7 +135,7 @@ pub trait Inspector { #[inline] fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -140,7 +149,7 @@ pub trait Inspector { /// This can happen from create TX or from EOFCREATE opcode. fn eofcreate( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut EOFCreateInputs, ) -> Option { let _ = context; @@ -151,7 +160,7 @@ pub trait Inspector { /// Called when eof creating has ended. fn eofcreate_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &EOFCreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index ed42c4f7b4..faa104062b 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -8,7 +8,7 @@ use revm_interpreter::OpCode; use crate::{ inspectors::GasInspector, interpreter::{CallInputs, CreateInputs, Interpreter}, - primitives::{Address, U256}, + primitives::{Address, ChainSpec, U256}, Database, EvmContext, Inspector, }; @@ -20,14 +20,18 @@ pub struct CustomPrintTracer { gas_inspector: GasInspector, } -impl Inspector for CustomPrintTracer { - fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { +impl Inspector for CustomPrintTracer { + fn initialize_interp( + &mut self, + interp: &mut Interpreter, + context: &mut EvmContext, + ) { self.gas_inspector.initialize_interp(interp, context); } // 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, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let opcode = interp.current_opcode(); let name = OpCode::name_by_op(opcode); @@ -52,13 +56,13 @@ impl Inspector for CustomPrintTracer { self.gas_inspector.step(interp, context); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); } fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -67,7 +71,7 @@ impl Inspector for CustomPrintTracer { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -76,7 +80,7 @@ impl Inspector for CustomPrintTracer { fn call( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, inputs: &mut CallInputs, ) -> Option { println!( @@ -93,7 +97,7 @@ impl Inspector for CustomPrintTracer { fn create( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { println!( diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index aec20ffd8f..6d22653280 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -3,7 +3,7 @@ use crate::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterResult, }, - primitives::{db::Database, hex, HashMap, B256, U256}, + primitives::{db::Database, hex, ChainSpec, HashMap, Transaction, B256, U256}, EvmContext, Inspector, }; use revm_interpreter::OpCode; @@ -162,10 +162,10 @@ impl TracerEip3155 { self.output.flush() } - fn print_summary( + fn print_summary( &mut self, result: &InterpreterResult, - context: &mut EvmContext, + context: &mut EvmContext, ) { if self.print_summary { let spec_name: &str = context.spec_id().into(); @@ -173,7 +173,7 @@ impl TracerEip3155 { state_root: B256::ZERO.to_string(), output: result.output.to_string(), gas_used: hex_number( - context.inner.env().tx.gas_limit - self.gas_inspector.gas_remaining(), + context.inner.env().tx.gas_limit() - self.gas_inspector.gas_remaining(), ), pass: result.is_ok(), time: None, @@ -184,12 +184,16 @@ impl TracerEip3155 { } } -impl Inspector for TracerEip3155 { - fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { +impl Inspector for TracerEip3155 { + fn initialize_interp( + &mut self, + interp: &mut Interpreter, + context: &mut EvmContext, + ) { self.gas_inspector.initialize_interp(interp, context); } - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step(interp, context); self.stack.clone_from(interp.stack.data()); self.memory = if self.include_memory { @@ -204,7 +208,7 @@ impl Inspector for TracerEip3155 { self.refunded = interp.gas.refunded(); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); if self.skip { self.skip = false; @@ -237,7 +241,7 @@ impl Inspector for TracerEip3155 { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -254,7 +258,7 @@ impl Inspector for TracerEip3155 { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 69f961efa4..ee9a4f377f 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -4,7 +4,7 @@ use revm_interpreter::CallOutcome; use crate::{ interpreter::{CallInputs, CreateInputs, CreateOutcome}, - primitives::db::Database, + primitives::{db::Database, ChainSpec}, EvmContext, Inspector, }; @@ -26,11 +26,11 @@ impl GasInspector { } } -impl Inspector for GasInspector { +impl Inspector for GasInspector { fn initialize_interp( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.gas_remaining = interp.gas.limit(); } @@ -38,7 +38,7 @@ impl Inspector for GasInspector { fn step( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.gas_remaining = interp.gas.remaining(); } @@ -46,7 +46,7 @@ impl Inspector for GasInspector { fn step_end( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { let remaining = interp.gas.remaining(); self.last_gas_cost = self.gas_remaining.saturating_sub(remaining); @@ -55,7 +55,7 @@ impl Inspector for GasInspector { fn call_end( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, _inputs: &CallInputs, mut outcome: CallOutcome, ) -> CallOutcome { @@ -68,7 +68,7 @@ impl Inspector for GasInspector { fn create_end( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, _inputs: &CreateInputs, mut outcome: CreateOutcome, ) -> CreateOutcome { @@ -82,16 +82,14 @@ impl Inspector for GasInspector { #[cfg(test)] mod tests { + use super::*; - use revm_interpreter::CallOutcome; - use revm_interpreter::CreateOutcome; + use crate::{interpreter::Interpreter, primitives::Log}; - use crate::{ - inspectors::GasInspector, - interpreter::{CallInputs, CreateInputs, Interpreter}, - primitives::Log, - Database, EvmContext, Inspector, - }; + #[cfg(feature = "optimism")] + type TestChainSpec = crate::optimism::OptimismChainSpec; + #[cfg(not(feature = "optimism"))] + type TestChainSpec = crate::primitives::EthChainSpec; #[derive(Default, Debug)] struct StackInspector { @@ -100,21 +98,30 @@ mod tests { gas_remaining_steps: Vec<(usize, u64)>, } - impl Inspector for StackInspector { - fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + impl Inspector for StackInspector { + fn initialize_interp( + &mut self, + interp: &mut Interpreter, + context: &mut EvmContext, + ) { self.gas_inspector.initialize_interp(interp, context); } - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.pc = interp.program_counter(); self.gas_inspector.step(interp, context); } - fn log(&mut self, interp: &mut Interpreter, context: &mut EvmContext, log: &Log) { + fn log( + &mut self, + interp: &mut Interpreter, + context: &mut EvmContext, + log: &Log, + ) { self.gas_inspector.log(interp, context, log); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); self.gas_remaining_steps .push((self.pc, self.gas_inspector.gas_remaining())); @@ -122,7 +129,7 @@ mod tests { fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, call: &mut CallInputs, ) -> Option { self.gas_inspector.call(context, call) @@ -130,7 +137,7 @@ mod tests { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -139,7 +146,7 @@ mod tests { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, call: &mut CreateInputs, ) -> Option { self.gas_inspector.create(context, call); @@ -148,7 +155,7 @@ mod tests { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -183,14 +190,27 @@ mod tests { ]); let bytecode = Bytecode::new_raw(contract_data); - let mut evm: Evm<'_, StackInspector, BenchmarkDB> = Evm::builder() + let mut evm = Evm::builder() + .with_chain_spec::() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { - tx.clear(); - tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); - tx.gas_limit = 21100; + *tx = ::Transaction::default(); + + #[cfg(feature = "optimism")] + let (caller, transact_to, gas_limit) = ( + &mut tx.base.caller, + &mut tx.base.transact_to, + &mut tx.base.gas_limit, + ); + + #[cfg(not(feature = "optimism"))] + let (caller, transact_to, gas_limit) = + (&mut tx.caller, &mut tx.transact_to, &mut tx.gas_limit); + + *caller = address!("1000000000000000000000000000000000000000"); + *transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); + *gas_limit = 21100; }) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 599ab9fc6a..f1d2e5c312 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -2,7 +2,7 @@ use crate::{ db::Database, handler::register::EvmHandler, interpreter::{opcode, InstructionResult, Interpreter}, - primitives::EVMError, + primitives::{ChainSpec, EVMError}, Context, FrameOrResult, FrameResult, Inspector, JournalEntry, }; use core::cell::RefCell; @@ -10,14 +10,16 @@ use revm_interpreter::opcode::DynInstruction; use std::{rc::Rc, sync::Arc, vec::Vec}; /// Provides access to an `Inspector` instance. -pub trait GetInspector { +pub trait GetInspector { /// Returns the associated `Inspector`. - fn get_inspector(&mut self) -> &mut impl Inspector; + fn get_inspector(&mut self) -> &mut impl Inspector; } -impl> GetInspector for INSP { +impl> + GetInspector for INSP +{ #[inline] - fn get_inspector(&mut self) -> &mut impl Inspector { + fn get_inspector(&mut self) -> &mut impl Inspector { self } } @@ -34,8 +36,12 @@ impl> GetInspector for INSP { /// A few instructions handlers are wrapped twice once for `step` and `step_end` /// and in case of Logs and Selfdestruct wrapper is wrapped again for the /// `log` and `selfdestruct` calls. -pub fn inspector_handle_register>( - handler: &mut EvmHandler<'_, EXT, DB>, +pub fn inspector_handle_register< + ChainSpecT: ChainSpec, + DB: Database, + EXT: GetInspector, +>( + handler: &mut EvmHandler<'_, ChainSpecT, EXT, DB>, ) { let table = &mut handler.instruction_table; @@ -90,7 +96,7 @@ pub fn inspector_handle_register>( let create_input_stack_inner = create_input_stack.clone(); let prev_handle = handler.execution.create.clone(); handler.execution.create = Arc::new( - move |ctx, mut inputs| -> Result> { + move |ctx, mut inputs| -> Result> { let inspector = ctx.external.get_inspector(); // call inspector create to change input or return outcome. if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { @@ -217,12 +223,12 @@ pub fn inspector_handle_register>( }); } -fn inspector_instruction( - prev: &DynInstruction<'_, Context>, +fn inspector_instruction( + prev: &DynInstruction<'_, Context>, interpreter: &mut Interpreter, - host: &mut Context, + host: &mut Context, ) where - INSP: GetInspector, + INSP: GetInspector, DB: Database, { // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the @@ -258,6 +264,11 @@ mod tests { Evm, EvmContext, }; + #[cfg(feature = "optimism")] + type TestChainSpec = crate::optimism::OptimismChainSpec; + #[cfg(not(feature = "optimism"))] + type TestChainSpec = crate::primitives::EthChainSpec; + #[derive(Default, Debug)] struct StackInspector { initialize_interp_called: bool, @@ -267,25 +278,33 @@ mod tests { call_end: bool, } - impl Inspector for StackInspector { - fn initialize_interp(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + impl Inspector for StackInspector { + fn initialize_interp( + &mut self, + _interp: &mut Interpreter, + _context: &mut EvmContext, + ) { if self.initialize_interp_called { unreachable!("initialize_interp should not be called twice") } self.initialize_interp_called = true; } - fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { self.step += 1; } - fn step_end(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + fn step_end( + &mut self, + _interp: &mut Interpreter, + _context: &mut EvmContext, + ) { self.step_end += 1; } fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _call: &mut CallInputs, ) -> Option { if self.call { @@ -298,7 +317,7 @@ mod tests { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -312,7 +331,7 @@ mod tests { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _call: &mut CreateInputs, ) -> Option { assert_eq!(context.journaled_state.depth(), 0); @@ -321,7 +340,7 @@ mod tests { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -356,14 +375,27 @@ mod tests { ]); let bytecode = Bytecode::new_raw(contract_data); - let mut evm: Evm<'_, StackInspector, BenchmarkDB> = Evm::builder() + let mut evm = Evm::builder() + .with_chain_spec::() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { - tx.clear(); - tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); - tx.gas_limit = 21100; + *tx = ::Transaction::default(); + + #[cfg(feature = "optimism")] + let (caller, transact_to, gas_limit) = ( + &mut tx.base.caller, + &mut tx.base.transact_to, + &mut tx.base.gas_limit, + ); + + #[cfg(not(feature = "optimism"))] + let (caller, transact_to, gas_limit) = + (&mut tx.caller, &mut tx.transact_to, &mut tx.gas_limit); + + *caller = address!("1000000000000000000000000000000000000000"); + *transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); + *gas_limit = 21100; }) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/revm/src/inspector/noop.rs b/crates/revm/src/inspector/noop.rs index 9e9556e286..fe0c295683 100644 --- a/crates/revm/src/inspector/noop.rs +++ b/crates/revm/src/inspector/noop.rs @@ -1,6 +1,6 @@ -use crate::{Database, Inspector}; +use crate::{primitives::ChainSpec, Database, Inspector}; /// Dummy [Inspector], helpful as standalone replacement. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoOpInspector; -impl Inspector for NoOpInspector {} +impl Inspector for NoOpInspector {} diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index a9cfa4ccee..7f75b4d710 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -1,9 +1,9 @@ use crate::{ interpreter::{InstructionResult, LoadAccountResult, SStoreResult, SelfDestructResult}, primitives::{ - db::Database, hash_map::Entry, Account, Address, Bytecode, EVMError, EvmState, - EvmStorageSlot, HashMap, HashSet, Log, SpecId, SpecId::*, TransientStorage, B256, - KECCAK_EMPTY, PRECOMPILE3, U256, + db::Database, hash_map::Entry, Account, Address, Bytecode, EvmState, EvmStorageSlot, + HashMap, HashSet, Log, SpecId, SpecId::*, TransientStorage, B256, KECCAK_EMPTY, + PRECOMPILE3, U256, }, }; use core::mem; @@ -194,7 +194,7 @@ impl JournaledState { to: &Address, balance: U256, db: &mut DB, - ) -> Result, EVMError> { + ) -> Result, DB::Error> { // load accounts self.load_account(*from, db)?; self.load_account(*to, db)?; @@ -477,7 +477,7 @@ impl JournaledState { address: Address, target: Address, db: &mut DB, - ) -> Result> { + ) -> Result { let load_result = self.load_account_exist(target, db)?; if address != target { @@ -539,13 +539,12 @@ impl JournaledState { address: Address, storage_keys: impl IntoIterator, db: &mut DB, - ) -> Result<&mut Account, EVMError> { + ) -> Result<&mut Account, DB::Error> { // load or get account. let account = match self.state.entry(address) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(vac) => vac.insert( - db.basic(address) - .map_err(EVMError::Database)? + db.basic(address)? .map(|i| i.into()) .unwrap_or(Account::new_not_existing()), ), @@ -553,9 +552,7 @@ impl JournaledState { // preload storages. for storage_key in storage_keys.into_iter() { if let Entry::Vacant(entry) = account.storage.entry(storage_key) { - let storage = db - .storage(address, storage_key) - .map_err(EVMError::Database)?; + let storage = db.storage(address, storage_key)?; entry.insert(EvmStorageSlot::new(storage)); } } @@ -568,7 +565,7 @@ impl JournaledState { &mut self, address: Address, db: &mut DB, - ) -> Result<(&mut Account, bool), EVMError> { + ) -> Result<(&mut Account, bool), DB::Error> { let (value, is_cold) = match self.state.entry(address) { Entry::Occupied(entry) => { let account = entry.into_mut(); @@ -576,12 +573,11 @@ impl JournaledState { (account, is_cold) } Entry::Vacant(vac) => { - let account = - if let Some(account) = db.basic(address).map_err(EVMError::Database)? { - account.into() - } else { - Account::new_not_existing() - }; + let account = if let Some(account) = db.basic(address)? { + account.into() + } else { + Account::new_not_existing() + }; // precompiles are warm loaded so we need to take that into account let is_cold = !self.warm_preloaded_addresses.contains(&address); @@ -609,7 +605,7 @@ impl JournaledState { &mut self, address: Address, db: &mut DB, - ) -> Result> { + ) -> Result { let spec = self.spec; let (acc, is_cold) = self.load_account(address, db)?; @@ -631,16 +627,14 @@ impl JournaledState { &mut self, address: Address, db: &mut DB, - ) -> Result<(&mut Account, bool), EVMError> { + ) -> Result<(&mut Account, bool), DB::Error> { let (acc, is_cold) = self.load_account(address, db)?; if acc.info.code.is_none() { if acc.info.code_hash == KECCAK_EMPTY { let empty = Bytecode::default(); acc.info.code = Some(empty); } else { - let code = db - .code_by_hash(acc.info.code_hash) - .map_err(EVMError::Database)?; + let code = db.code_by_hash(acc.info.code_hash)?; acc.info.code = Some(code); } } @@ -658,7 +652,7 @@ impl JournaledState { address: Address, key: U256, db: &mut DB, - ) -> Result<(U256, bool), EVMError> { + ) -> Result<(U256, bool), DB::Error> { // assume acc is warm let account = self.state.get_mut(&address).unwrap(); // only if account is created in this tx we can assume that storage is empty. @@ -674,7 +668,7 @@ impl JournaledState { let value = if is_newly_created { U256::ZERO } else { - db.storage(address, key).map_err(EVMError::Database)? + db.storage(address, key)? }; vac.insert(EvmStorageSlot::new(value)); @@ -707,7 +701,7 @@ impl JournaledState { key: U256, new: U256, db: &mut DB, - ) -> Result> { + ) -> Result { // assume that acc exists and load the slot. let (present, is_cold) = self.sload(address, key, db)?; let acc = self.state.get_mut(&address).unwrap(); diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 5097388526..cb42740d71 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -29,7 +29,7 @@ pub use builder::EvmBuilder; pub use context::{ Context, ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, - ContextWithHandlerCfg, EvmContext, InnerEvmContext, + ContextWithChainSpec, EvmContext, InnerEvmContext, }; pub use db::{ CacheState, DBBox, State, StateBuilder, StateDBBox, TransitionAccount, TransitionState, @@ -37,7 +37,7 @@ pub use db::{ pub use db::{Database, DatabaseCommit, DatabaseRef, InMemoryDB}; pub use evm::{Evm, CALL_STACK_LIMIT}; pub use frame::{CallFrame, CreateFrame, Frame, FrameData, FrameOrResult, FrameResult}; -pub use handler::Handler; +pub use handler::{register::EvmHandler, Handler}; pub use inspector::{inspector_handle_register, inspectors, GetInspector, Inspector}; pub use journaled_state::{JournalCheckpoint, JournalEntry, JournaledState}; // export Optimism types, helpers, and constants diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index 12f3db9969..b2edd651ee 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -1,11 +1,17 @@ //! Optimism-specific constants, types, and helpers. +mod env; mod fast_lz; +mod handler; mod handler_register; mod l1block; +mod result; +mod spec; pub use handler_register::{ - deduct_caller, end, last_frame_return, load_accounts, load_precompiles, - optimism_handle_register, output, reward_beneficiary, validate_env, validate_tx_against_state, + deduct_caller, end, last_frame_return, load_precompiles, optimism_handle_register, output, + reward_beneficiary, validate_env, validate_tx_against_state, }; pub use l1block::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; +pub use result::{OptimismHaltReason, OptimismInvalidTransaction}; +pub use spec::*; diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs new file mode 100644 index 0000000000..4c4c29c59e --- /dev/null +++ b/crates/revm/src/optimism/env.rs @@ -0,0 +1,171 @@ +use crate::{ + primitives::{ + db::Database, AccessListItem, Address, AuthorizationList, BlobExcessGasAndPrice, Block, + BlockEnv, Bytes, TransactTo, Transaction, TxEnv, B256, U256, + }, + L1BlockInfo, +}; + +use super::{OptimismInvalidTransaction, OptimismSpecId}; + +/// The Optimism block environment. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct OptimismBlock { + pub base: BlockEnv, + /// L1 block info used to compute the L1-cost fee. + /// + /// Needs to be provided for Optimism non-deposit transactions. + l1_block_info: Option, +} + +impl OptimismBlock { + /// Constructs a new instance. + pub fn new(base: BlockEnv, l1_block_info: Option) -> Self { + Self { + base, + l1_block_info, + } + } + + /// Create a new Optimism block environment. + pub fn with_l1_block_info( + base: BlockEnv, + db: &mut DB, + spec_id: OptimismSpecId, + ) -> Result { + let l1_block_info = L1BlockInfo::try_fetch(db, spec_id)?; + + Ok(Self { + base, + l1_block_info: Some(l1_block_info), + }) + } + + /// Retrieves the L1 block info. + pub fn l1_block_info(&self) -> Option<&L1BlockInfo> { + self.l1_block_info.as_ref() + } +} + +impl Block for OptimismBlock { + fn number(&self) -> &U256 { + self.base.number() + } + + fn coinbase(&self) -> &Address { + self.base.coinbase() + } + + fn timestamp(&self) -> &U256 { + self.base.timestamp() + } + + fn gas_limit(&self) -> &U256 { + self.base.gas_limit() + } + + fn basefee(&self) -> &U256 { + self.base.basefee() + } + + fn difficulty(&self) -> &U256 { + self.base.difficulty() + } + + fn prevrandao(&self) -> Option<&B256> { + self.base.prevrandao() + } + + fn blob_excess_gas_and_price(&self) -> Option<&BlobExcessGasAndPrice> { + self.base.blob_excess_gas_and_price() + } +} + +/// The Optimism transaction environment. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct OptimismTransaction { + #[cfg_attr(feature = "serde", serde(flatten))] + pub base: TxEnv, + + /// The source hash is used to make sure that deposit transactions do + /// not have identical hashes. + /// + /// L1 originated deposit transaction source hashes are computed using + /// the hash of the l1 block hash and the l1 log index. + /// L1 attributes deposit source hashes are computed with the l1 block + /// hash and the sequence number = l2 block number - l2 epoch start + /// block number. + /// + /// These two deposit transaction sources specify a domain in the outer + /// hash so there are no collisions. + pub source_hash: Option, + /// The amount to increase the balance of the `from` account as part of + /// a deposit transaction. This is unconditional and is applied to the + /// `from` account even if the deposit transaction fails since + /// the deposit is pre-paid on L1. + pub mint: Option, + /// Whether or not the transaction is a system transaction. + pub is_system_transaction: Option, + /// An enveloped EIP-2718 typed transaction. This is used + /// to compute the L1 tx cost using the L1 block info, as + /// opposed to requiring downstream apps to compute the cost + /// externally. + pub enveloped_tx: Option, +} + +impl Transaction for OptimismTransaction { + type TransactionValidationError = OptimismInvalidTransaction; + + fn caller(&self) -> &Address { + self.base.caller() + } + + fn gas_limit(&self) -> u64 { + self.base.gas_limit() + } + + fn gas_price(&self) -> &U256 { + self.base.gas_price() + } + + fn transact_to(&self) -> &TransactTo { + self.base.transact_to() + } + + fn value(&self) -> &U256 { + self.base.value() + } + + fn data(&self) -> &Bytes { + self.base.data() + } + + fn nonce(&self) -> Option { + self.base.nonce() + } + + fn chain_id(&self) -> Option { + self.base.chain_id() + } + + fn access_list(&self) -> &[AccessListItem] { + self.base.access_list() + } + + fn gas_priority_fee(&self) -> Option<&U256> { + self.base.gas_priority_fee() + } + + fn blob_hashes(&self) -> &[B256] { + self.base.blob_hashes() + } + + fn max_fee_per_blob_gas(&self) -> Option<&U256> { + self.base.max_fee_per_blob_gas() + } + + fn authorization_list(&self) -> Option<&AuthorizationList> { + self.base.authorization_list() + } +} diff --git a/crates/revm/src/optimism/handler.rs b/crates/revm/src/optimism/handler.rs new file mode 100644 index 0000000000..1002b429c6 --- /dev/null +++ b/crates/revm/src/optimism/handler.rs @@ -0,0 +1,19 @@ +use crate::{ + handler::register::{EvmHandler, HandleRegisters}, + primitives::db::Database, +}; + +use super::OptimismChainSpec; + +impl EvmHandler<'_, OptimismChainSpec, EXT, DB> { + /// Optimism with spec. Similar to [`Self::mainnet_with_spec`]. + pub fn optimism_with_spec(spec_id: crate::optimism::OptimismSpecId) -> Self { + let mut handler = Self::mainnet_with_spec(spec_id); + + handler.append_handler_register(HandleRegisters::Plain( + crate::optimism::optimism_handle_register::, + )); + + handler + } +} diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 348b9cf797..576da94fd7 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -6,11 +6,10 @@ use crate::{ register::EvmHandler, }, interpreter::{return_ok, return_revert, Gas, InstructionResult}, - optimism, + optimism, optimism_spec_to_generic, primitives::{ - db::Database, spec_to_generic, Account, EVMError, Env, ExecutionResult, HaltReason, - HashMap, InvalidTransaction, OptimismInvalidTransaction, ResultAndState, Spec, SpecId, - SpecId::REGOLITH, U256, + db::Database, Account, Block, EVMError, Env, ExecutionResult, HashMap, InvalidTransaction, + ResultAndState, Transaction, U256, }, Context, ContextPrecompiles, FrameResult, }; @@ -19,8 +18,14 @@ use revm_precompile::{secp256r1, PrecompileSpecId}; use std::string::ToString; use std::sync::Arc; -pub fn optimism_handle_register(handler: &mut EvmHandler<'_, EXT, DB>) { - spec_to_generic!(handler.cfg.spec_id, { +use super::{ + OptimismChainSpec, OptimismHaltReason, OptimismInvalidTransaction, OptimismSpec, OptimismSpecId, +}; + +pub fn optimism_handle_register( + handler: &mut EvmHandler<'_, OptimismChainSpec, EXT, DB>, +) { + optimism_spec_to_generic!(handler.spec_id, { // validate environment handler.validation.env = Arc::new(validate_env::); // Validate transaction against state. @@ -28,7 +33,8 @@ pub fn optimism_handle_register(handler: &mut EvmHandler<'_, // Load additional precompiles for the given chain spec. handler.pre_execution.load_precompiles = Arc::new(load_precompiles::); // load l1 data - handler.pre_execution.load_accounts = Arc::new(load_accounts::); + handler.pre_execution.load_accounts = + Arc::new(mainnet::load_accounts::); // An estimated batch cost is charged from the caller and added to L1 Fee Vault. handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); // Refund is calculated differently then mainnet. @@ -41,48 +47,58 @@ pub fn optimism_handle_register(handler: &mut EvmHandler<'_, } /// Validate environment for the Optimism chain. -pub fn validate_env(env: &Env) -> Result<(), EVMError> { +pub fn validate_env( + env: &Env, +) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. - if env.tx.optimism.source_hash.is_some() { - return Ok(()); + if env.tx.source_hash.is_some() { + if env.block.l1_block_info().is_some() { + return Err(OptimismInvalidTransaction::UnexpectedL1BlockInfo.into()); + } else { + return Ok(()); + } } + // Important: validate block before tx. env.validate_block_env::()?; + if env.block.l1_block_info().is_none() { + return Err(OptimismInvalidTransaction::MissingL1BlockInfo.into()); + } + // Do not allow for a system transaction to be processed if Regolith is enabled. - let tx = &env.tx.optimism; - if tx.is_system_transaction.unwrap_or(false) && SPEC::enabled(SpecId::REGOLITH) { - return Err(InvalidTransaction::OptimismError( - OptimismInvalidTransaction::DepositSystemTxPostRegolith, - ) - .into()); + if env.tx.is_system_transaction.unwrap_or(false) + && SPEC::optimism_enabled(OptimismSpecId::REGOLITH) + { + return Err(OptimismInvalidTransaction::DepositSystemTxPostRegolith.into()); } - env.validate_tx::()?; + env.validate_tx::() + .map_err(OptimismInvalidTransaction::Base)?; Ok(()) } /// Don not perform any extra validation for deposit transactions, they are pre-verified on L1. -pub fn validate_tx_against_state( - context: &mut Context, -) -> Result<(), EVMError> { - if context.evm.inner.env.tx.optimism.source_hash.is_some() { +pub fn validate_tx_against_state( + context: &mut Context, +) -> Result<(), EVMError> { + if context.evm.inner.env.tx.source_hash.is_some() { return Ok(()); } - mainnet::validate_tx_against_state::(context) + mainnet::validate_tx_against_state::(context) } /// Handle output of the transaction #[inline] -pub fn last_frame_return( - context: &mut Context, +pub fn last_frame_return( + context: &mut Context, frame_result: &mut FrameResult, -) -> Result<(), EVMError> { +) -> Result<(), EVMError> { let env = context.evm.inner.env(); - let is_deposit = env.tx.optimism.source_hash.is_some(); - let tx_system = env.tx.optimism.is_system_transaction; - let tx_gas_limit = env.tx.gas_limit; - let is_regolith = SPEC::enabled(REGOLITH); + let is_deposit = env.tx.source_hash.is_some(); + let tx_system = env.tx.is_system_transaction; + let tx_gas_limit = env.tx.gas_limit(); + let is_regolith = SPEC::optimism_enabled(OptimismSpecId::REGOLITH); let instruction_result = frame_result.interpreter_result().result; let gas = frame_result.gas_mut(); @@ -139,17 +155,18 @@ pub fn last_frame_return( // Prior to Regolith, deposit transactions did not receive gas refunds. let is_gas_refund_disabled = env.cfg.is_gas_refund_disabled() || (is_deposit && !is_regolith); if !is_gas_refund_disabled { - gas.set_final_refund(SPEC::SPEC_ID.is_enabled_in(SpecId::LONDON)); + gas.set_final_refund(SPEC::OPTIMISM_SPEC_ID.is_enabled_in(OptimismSpecId::LONDON)); } Ok(()) } /// Load precompiles for Optimism chain. #[inline] -pub fn load_precompiles() -> ContextPrecompiles { +pub fn load_precompiles( +) -> ContextPrecompiles { let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)); - if SPEC::enabled(SpecId::FJORD) { + if SPEC::optimism_enabled(OptimismSpecId::FJORD) { precompiles.extend([ // EIP-7212: secp256r1 P256verify secp256r1::P256VERIFY, @@ -159,53 +176,38 @@ pub fn load_precompiles() -> ContextPrecompiles( - context: &mut Context, -) -> Result<(), EVMError> { - // the L1-cost fee is only computed for Optimism non-deposit transactions. - - if context.evm.inner.env.tx.optimism.source_hash.is_none() { - let l1_block_info = - crate::optimism::L1BlockInfo::try_fetch(&mut context.evm.inner.db, SPEC::SPEC_ID) - .map_err(EVMError::Database)?; - - // storage l1 block info for later use. - context.evm.inner.l1_block_info = Some(l1_block_info); - } - - mainnet::load_accounts::(context) -} - /// Deduct max balance from caller #[inline] -pub fn deduct_caller( - context: &mut Context, -) -> Result<(), EVMError> { +pub fn deduct_caller( + context: &mut Context, +) -> Result<(), EVMError> { // load caller's account. let (caller_account, _) = context .evm .inner .journaled_state - .load_account(context.evm.inner.env.tx.caller, &mut context.evm.inner.db)?; + .load_account( + *context.evm.inner.env.tx.caller(), + &mut context.evm.inner.db, + ) + .map_err(EVMError::Database)?; // If the transaction is a deposit with a `mint` value, add the mint value // in wei to the caller's balance. This should be persisted to the database // prior to the rest of execution. - if let Some(mint) = context.evm.inner.env.tx.optimism.mint { + if let Some(mint) = context.evm.inner.env.tx.mint { caller_account.info.balance += U256::from(mint); } // We deduct caller max balance after minting and before deducing the // l1 cost, max values is already checked in pre_validate but l1 cost wasn't. - deduct_caller_inner::(caller_account, &context.evm.inner.env); + deduct_caller_inner::(caller_account, &context.evm.inner.env); // If the transaction is not a deposit transaction, subtract the L1 data fee from the // caller's balance directly after minting the requested amount of ETH. - if context.evm.inner.env.tx.optimism.source_hash.is_none() { + if context.evm.inner.env.tx.source_hash.is_none() { // get envelope - let Some(enveloped_tx) = &context.evm.inner.env.tx.optimism.enveloped_tx else { + let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx else { return Err(EVMError::Custom( "[OPTIMISM] Failed to load enveloped transaction.".to_string(), )); @@ -214,16 +216,18 @@ pub fn deduct_caller( let tx_l1_cost = context .evm .inner - .l1_block_info - .as_ref() + .env + .block + .l1_block_info() .expect("L1BlockInfo should be loaded") - .calculate_tx_l1_cost(enveloped_tx, SPEC::SPEC_ID); + .calculate_tx_l1_cost(enveloped_tx, SPEC::OPTIMISM_SPEC_ID); if tx_l1_cost.gt(&caller_account.info.balance) { return Err(EVMError::Transaction( InvalidTransaction::LackOfFundForMaxFee { fee: tx_l1_cost.into(), balance: caller_account.info.balance.into(), - }, + } + .into(), )); } caller_account.info.balance = caller_account.info.balance.saturating_sub(tx_l1_cost); @@ -233,40 +237,43 @@ pub fn deduct_caller( /// Reward beneficiary with gas fee. #[inline] -pub fn reward_beneficiary( - context: &mut Context, +pub fn reward_beneficiary( + context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { - let is_deposit = context.evm.inner.env.tx.optimism.source_hash.is_some(); +) -> Result<(), EVMError> { + let is_deposit = context.evm.inner.env.tx.source_hash.is_some(); // transfer fee to coinbase/beneficiary. if !is_deposit { - mainnet::reward_beneficiary::(context, gas)?; + mainnet::reward_beneficiary::(context, gas)?; } if !is_deposit { // If the transaction is not a deposit transaction, fees are paid out // to both the Base Fee Vault as well as the L1 Fee Vault. - let Some(l1_block_info) = &context.evm.inner.l1_block_info else { - return Err(EVMError::Custom( - "[OPTIMISM] Failed to load L1 block information.".to_string(), - )); - }; + let l1_block_info = context + .evm + .inner + .env + .block + .l1_block_info() + .expect("L1BlockInfo should be loaded"); - let Some(enveloped_tx) = &context.evm.inner.env.tx.optimism.enveloped_tx else { + let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx else { return Err(EVMError::Custom( "[OPTIMISM] Failed to load enveloped transaction.".to_string(), )); }; - let l1_cost = l1_block_info.calculate_tx_l1_cost(enveloped_tx, SPEC::SPEC_ID); + let l1_cost = l1_block_info.calculate_tx_l1_cost(enveloped_tx, SPEC::OPTIMISM_SPEC_ID); // Send the L1 cost of the transaction to the L1 Fee Vault. let (l1_fee_vault_account, _) = context .evm .inner .journaled_state - .load_account(optimism::L1_FEE_RECIPIENT, &mut context.evm.inner.db)?; + .load_account(optimism::L1_FEE_RECIPIENT, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; l1_fee_vault_account.mark_touch(); l1_fee_vault_account.info.balance += l1_cost; @@ -275,14 +282,15 @@ pub fn reward_beneficiary( .evm .inner .journaled_state - .load_account(optimism::BASE_FEE_RECIPIENT, &mut context.evm.inner.db)?; + .load_account(optimism::BASE_FEE_RECIPIENT, &mut context.evm.inner.db) + .map_err(EVMError::Database)?; base_fee_vault_account.mark_touch(); base_fee_vault_account.info.balance += context .evm .inner .env .block - .basefee + .basefee() .mul(U256::from(gas.spent() - gas.refunded() as u64)); } Ok(()) @@ -290,21 +298,21 @@ pub fn reward_beneficiary( /// Main return handle, returns the output of the transaction. #[inline] -pub fn output( - context: &mut Context, +pub fn output( + context: &mut Context, frame_result: FrameResult, -) -> Result> { - let result = mainnet::output::(context, frame_result)?; +) -> Result, EVMError> { + let result = mainnet::output::(context, frame_result)?; if result.result.is_halt() { // Post-regolith, if the transaction is a deposit transaction and it halts, // we bubble up to the global return handler. The mint value will be persisted // and the caller nonce will be incremented there. - let is_deposit = context.evm.inner.env.tx.optimism.source_hash.is_some(); - if is_deposit && SPEC::enabled(REGOLITH) { - return Err(EVMError::Transaction(InvalidTransaction::OptimismError( + let is_deposit = context.evm.inner.env.tx.source_hash.is_some(); + if is_deposit && SPEC::optimism_enabled(OptimismSpecId::REGOLITH) { + return Err(EVMError::Transaction( OptimismInvalidTransaction::HaltedDepositPostRegolith, - ))); + )); } } Ok(result) @@ -312,13 +320,13 @@ pub fn output( /// Optimism end handle changes output if the transaction is a deposit transaction. /// Deposit transaction can't be reverted and is always successful. #[inline] -pub fn end( - context: &mut Context, - evm_output: Result>, -) -> Result> { +pub fn end( + context: &mut Context, + evm_output: Result, EVMError>, +) -> Result, EVMError> { evm_output.or_else(|err| { if matches!(err, EVMError::Transaction(_)) - && context.evm.inner.env().tx.optimism.source_hash.is_some() + && context.evm.inner.env().tx.source_hash.is_some() { // If the transaction is a deposit transaction and it failed // for any reason, the caller nonce must be bumped, and the @@ -326,7 +334,7 @@ pub fn end( // also returned as a special Halt variant so that consumers can more // easily distinguish between a failed deposit and a failed // normal transaction. - let caller = context.evm.inner.env().tx.caller; + let caller = *context.evm.inner.env().tx.caller(); // Increment sender nonce and account balance for the mint amount. Deposits // always persist the mint amount, even if the transaction fails. @@ -340,9 +348,10 @@ pub fn end( .unwrap_or_default(), ); acc.info.nonce = acc.info.nonce.saturating_add(1); - acc.info.balance = acc.info.balance.saturating_add(U256::from( - context.evm.inner.env().tx.optimism.mint.unwrap_or(0), - )); + acc.info.balance = acc + .info + .balance + .saturating_add(U256::from(context.evm.inner.env().tx.mint.unwrap_or(0))); acc.mark_touch(); acc }; @@ -352,22 +361,16 @@ pub fn end( // limit of the transaction. pre-regolith, it is the gas limit // of the transaction for non system transactions and 0 for system // transactions. - let is_system_tx = context - .evm - .env() - .tx - .optimism - .is_system_transaction - .unwrap_or(false); - let gas_used = if SPEC::enabled(REGOLITH) || !is_system_tx { - context.evm.inner.env().tx.gas_limit + let is_system_tx = context.evm.env().tx.is_system_transaction.unwrap_or(false); + let gas_used = if SPEC::optimism_enabled(OptimismSpecId::REGOLITH) || !is_system_tx { + context.evm.inner.env().tx.gas_limit() } else { 0 }; Ok(ResultAndState { result: ExecutionResult::Halt { - reason: HaltReason::FailedDeposit, + reason: OptimismHaltReason::FailedDeposit, gas_used, }, state, @@ -385,16 +388,14 @@ mod tests { use super::*; use crate::{ db::{EmptyDB, InMemoryDB}, - primitives::{ - bytes, state::AccountInfo, Address, BedrockSpec, Bytes, Env, LatestSpec, RegolithSpec, - B256, - }, + optimism::{env::OptimismBlock, BedrockSpec, LatestSpec, RegolithSpec}, + primitives::{bytes, state::AccountInfo, Address, BlockEnv, Bytes, Env, B256}, L1BlockInfo, }; /// Creates frame result. - fn call_last_frame_return( - env: Env, + fn call_last_frame_return( + env: Env, instruction_result: InstructionResult, gas: Gas, ) -> Gas { @@ -414,9 +415,9 @@ mod tests { #[test] fn test_revert_gas() { - let mut env = Env::default(); - env.tx.gas_limit = 100; - env.tx.optimism.source_hash = None; + let mut env = Env::::default(); + env.tx.base.gas_limit = 100; + env.tx.source_hash = None; let gas = call_last_frame_return::(env, InstructionResult::Revert, Gas::new(90)); @@ -427,9 +428,9 @@ mod tests { #[test] fn test_consume_gas() { - let mut env = Env::default(); - env.tx.gas_limit = 100; - env.tx.optimism.source_hash = Some(B256::ZERO); + let mut env = Env::::default(); + env.tx.base.gas_limit = 100; + env.tx.source_hash = Some(B256::ZERO); let gas = call_last_frame_return::(env, InstructionResult::Stop, Gas::new(90)); @@ -440,9 +441,9 @@ mod tests { #[test] fn test_consume_gas_with_refund() { - let mut env = Env::default(); - env.tx.gas_limit = 100; - env.tx.optimism.source_hash = Some(B256::ZERO); + let mut env = Env::::default(); + env.tx.base.gas_limit = 100; + env.tx.source_hash = Some(B256::ZERO); let mut ret_gas = Gas::new(90); ret_gas.record_refund(20); @@ -461,9 +462,9 @@ mod tests { #[test] fn test_consume_gas_sys_deposit_tx() { - let mut env = Env::default(); - env.tx.gas_limit = 100; - env.tx.optimism.source_hash = Some(B256::ZERO); + let mut env = Env::::default(); + env.tx.base.gas_limit = 100; + env.tx.source_hash = Some(B256::ZERO); let gas = call_last_frame_return::(env, InstructionResult::Stop, Gas::new(90)); assert_eq!(gas.remaining(), 0); @@ -482,17 +483,21 @@ mod tests { ..Default::default() }, ); - let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); - context.evm.inner.l1_block_info = Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..Default::default() - }); + + let mut context: Context = Context::new_with_db(db); + context.evm.inner.env.block = OptimismBlock::new( + BlockEnv::default(), + Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..L1BlockInfo::default() + }), + ); // Enveloped needs to be some but it will deduce zero fee. - context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("")); + context.evm.inner.env.tx.enveloped_tx = Some(bytes!("")); // added mint value is 10. - context.evm.inner.env.tx.optimism.mint = Some(10); + context.evm.inner.env.tx.mint = Some(10); deduct_caller::(&mut context).unwrap(); @@ -517,20 +522,23 @@ mod tests { ..Default::default() }, ); - let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); - context.evm.inner.l1_block_info = Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..Default::default() - }); + let mut context: Context = Context::new_with_db(db); + context.evm.inner.env.block = OptimismBlock::new( + BlockEnv::default(), + Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..L1BlockInfo::default() + }), + ); // l1block cost is 1048 fee. - context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("FACADE")); + context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); // added mint value is 10. - context.evm.inner.env.tx.optimism.mint = Some(10); + context.evm.inner.env.tx.mint = Some(10); // Putting source_hash to some makes it a deposit transaction. // so enveloped_tx gas cost is ignored. - context.evm.inner.env.tx.optimism.source_hash = Some(B256::ZERO); + context.evm.inner.env.tx.source_hash = Some(B256::ZERO); deduct_caller::(&mut context).unwrap(); @@ -555,15 +563,18 @@ mod tests { ..Default::default() }, ); - let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); - context.evm.inner.l1_block_info = Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..Default::default() - }); + let mut context: Context = Context::new_with_db(db); + context.evm.inner.env.block = OptimismBlock::new( + BlockEnv::default(), + Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..L1BlockInfo::default() + }), + ); // l1block cost is 1048 fee. - context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("FACADE")); + context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. @@ -587,15 +598,18 @@ mod tests { ..Default::default() }, ); - let mut context: Context<(), InMemoryDB> = Context::new_with_db(db); - context.evm.inner.l1_block_info = Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..Default::default() - }); + let mut context: Context = Context::new_with_db(db); + context.evm.inner.env.block = OptimismBlock::new( + BlockEnv::default(), + Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..L1BlockInfo::default() + }), + ); // l1block cost is 1048 fee. - context.evm.inner.env.tx.optimism.enveloped_tx = Some(bytes!("FACADE")); + context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); assert_eq!( deduct_caller::(&mut context), @@ -603,7 +617,8 @@ mod tests { InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(U256::from(1048)), balance: Box::new(U256::from(48)), - }, + } + .into(), )) ); } @@ -611,13 +626,24 @@ mod tests { #[test] fn test_validate_sys_tx() { // mark the tx as a system transaction. - let mut env = Env::default(); - env.tx.optimism.is_system_transaction = Some(true); + let mut env = Env:: { + block: OptimismBlock::new( + BlockEnv::default(), + Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..L1BlockInfo::default() + }), + ), + ..Env::default() + }; + env.tx.is_system_transaction = Some(true); assert_eq!( validate_env::(&env), - Err(EVMError::Transaction(InvalidTransaction::OptimismError( + Err(EVMError::Transaction( OptimismInvalidTransaction::DepositSystemTxPostRegolith - ))) + )) ); // Pre-regolith system transactions should be allowed. @@ -627,16 +653,16 @@ mod tests { #[test] fn test_validate_deposit_tx() { // Set source hash. - let mut env = Env::default(); - env.tx.optimism.source_hash = Some(B256::ZERO); + let mut env = Env::::default(); + env.tx.source_hash = Some(B256::ZERO); assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_tx_against_state_deposit_tx() { // Set source hash. - let mut env = Env::default(); - env.tx.optimism.source_hash = Some(B256::ZERO); + let mut env = Env::::default(); + env.tx.source_hash = Some(B256::ZERO); // Nonce and balance checks should be skipped for deposit transactions. assert!(validate_env::(&env).is_ok()); diff --git a/crates/revm/src/optimism/l1block.rs b/crates/revm/src/optimism/l1block.rs index 86e32850fa..db4929e304 100644 --- a/crates/revm/src/optimism/l1block.rs +++ b/crates/revm/src/optimism/l1block.rs @@ -1,7 +1,9 @@ use crate::optimism::fast_lz::flz_compress_len; -use crate::primitives::{address, db::Database, Address, SpecId, U256}; +use crate::primitives::{address, db::Database, Address, U256}; use core::ops::Mul; +use super::OptimismSpecId; + const ZERO_BYTE_COST: u64 = 4; const NON_ZERO_BYTE_COST: u64 = 16; @@ -46,7 +48,7 @@ pub const L1_BLOCK_CONTRACT: Address = address!("4200000000000000000000000000000 /// uint64 _sequenceNumber, bytes32 _batcherHash, uint256 _l1FeeOverhead, uint256 _l1FeeScalar) /// /// For now, we only care about the fields necessary for L1 cost calculation. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct L1BlockInfo { /// The base fee of the L1 origin block. pub l1_base_fee: U256, @@ -64,16 +66,19 @@ pub struct L1BlockInfo { impl L1BlockInfo { /// Try to fetch the L1 block info from the database. - pub fn try_fetch(db: &mut DB, spec_id: SpecId) -> Result { + pub fn try_fetch( + db: &mut DB, + spec_id: OptimismSpecId, + ) -> Result { // Ensure the L1 Block account is loaded into the cache after Ecotone. With EIP-4788, it is no longer the case // that the L1 block account is loaded into the cache prior to the first inquiry for the L1 block info. - if spec_id.is_enabled_in(SpecId::CANCUN) { + if spec_id.is_enabled_in(OptimismSpecId::CANCUN) { let _ = db.basic(L1_BLOCK_CONTRACT)?; } let l1_base_fee = db.storage(L1_BLOCK_CONTRACT, L1_BASE_FEE_SLOT)?; - if !spec_id.is_enabled_in(SpecId::ECOTONE) { + if !spec_id.is_enabled_in(OptimismSpecId::ECOTONE) { let l1_fee_overhead = db.storage(L1_BLOCK_CONTRACT, L1_OVERHEAD_SLOT)?; let l1_fee_scalar = db.storage(L1_BLOCK_CONTRACT, L1_SCALAR_SLOT)?; @@ -124,8 +129,8 @@ impl L1BlockInfo { /// /// Prior to regolith, an extra 68 non-zero bytes were included in the rollup data costs to /// account for the empty signature. - pub fn data_gas(&self, input: &[u8], spec_id: SpecId) -> U256 { - if spec_id.is_enabled_in(SpecId::FJORD) { + pub fn data_gas(&self, input: &[u8], spec_id: OptimismSpecId) -> U256 { + if spec_id.is_enabled_in(OptimismSpecId::FJORD) { let estimated_size = self.tx_estimated_size_fjord(input); return estimated_size @@ -142,7 +147,7 @@ impl L1BlockInfo { })); // Prior to regolith, an extra 68 non zero bytes were included in the rollup data costs. - if !spec_id.is_enabled_in(SpecId::REGOLITH) { + if !spec_id.is_enabled_in(OptimismSpecId::REGOLITH) { rollup_data_gas_cost += U256::from(NON_ZERO_BYTE_COST).mul(U256::from(68)); } @@ -161,16 +166,16 @@ impl L1BlockInfo { .max(U256::from(100_000_000)) } - /// Calculate the gas cost of a transaction based on L1 block data posted on L2, depending on the [SpecId] passed. - pub fn calculate_tx_l1_cost(&self, input: &[u8], spec_id: SpecId) -> U256 { + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, depending on the [OptimismSpecId] passed. + pub fn calculate_tx_l1_cost(&self, input: &[u8], spec_id: OptimismSpecId) -> U256 { // If the input is a deposit transaction or empty, the default value is zero. if input.is_empty() || input.first() == Some(&0x7F) { return U256::ZERO; } - if spec_id.is_enabled_in(SpecId::FJORD) { + if spec_id.is_enabled_in(OptimismSpecId::FJORD) { self.calculate_tx_l1_cost_fjord(input) - } else if spec_id.is_enabled_in(SpecId::ECOTONE) { + } else if spec_id.is_enabled_in(OptimismSpecId::ECOTONE) { self.calculate_tx_l1_cost_ecotone(input, spec_id) } else { self.calculate_tx_l1_cost_bedrock(input, spec_id) @@ -178,7 +183,7 @@ impl L1BlockInfo { } /// Calculate the gas cost of a transaction based on L1 block data posted on L2, pre-Ecotone. - fn calculate_tx_l1_cost_bedrock(&self, input: &[u8], spec_id: SpecId) -> U256 { + fn calculate_tx_l1_cost_bedrock(&self, input: &[u8], spec_id: OptimismSpecId) -> U256 { let rollup_data_gas_cost = self.data_gas(input, spec_id); rollup_data_gas_cost .saturating_add(self.l1_fee_overhead.unwrap_or_default()) @@ -189,7 +194,7 @@ impl L1BlockInfo { /// Calculate the gas cost of a transaction based on L1 block data posted on L2, post-Ecotone. /// - /// [SpecId::ECOTONE] L1 cost function: + /// [OptimismSpecId::ECOTONE] L1 cost function: /// `(calldataGas/16)*(l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar)/1e6` /// /// We divide "calldataGas" by 16 to change from units of calldata gas to "estimated # of bytes when compressed". @@ -197,7 +202,7 @@ impl L1BlockInfo { /// /// Function is actually computed as follows for better precision under integer arithmetic: /// `calldataGas*(l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar)/16e6` - fn calculate_tx_l1_cost_ecotone(&self, input: &[u8], spec_id: SpecId) -> U256 { + fn calculate_tx_l1_cost_ecotone(&self, input: &[u8], spec_id: OptimismSpecId) -> U256 { // There is an edgecase where, for the very first Ecotone block (unless it is activated at Genesis), we must // use the Bedrock cost function. To determine if this is the case, we can check if the Ecotone parameters are // unset. @@ -215,7 +220,7 @@ impl L1BlockInfo { /// Calculate the gas cost of a transaction based on L1 block data posted on L2, post-Fjord. /// - /// [SpecId::FJORD] L1 cost function: + /// [OptimismSpecId::FJORD] L1 cost function: /// `estimatedSize*(baseFeeScalar*l1BaseFee*16 + blobFeeScalar*l1BlobBaseFee)/1e12` fn calculate_tx_l1_cost_fjord(&self, input: &[u8]) -> U256 { let l1_fee_scaled = self.calculate_l1_fee_scaled_ecotone(); @@ -262,17 +267,17 @@ mod tests { // gas cost = 3 non-zero bytes * NON_ZERO_BYTE_COST + NON_ZERO_BYTE_COST * 68 // gas cost = 3 * 16 + 68 * 16 = 1136 let input = bytes!("FACADE"); - let bedrock_data_gas = l1_block_info.data_gas(&input, SpecId::BEDROCK); + let bedrock_data_gas = l1_block_info.data_gas(&input, OptimismSpecId::BEDROCK); assert_eq!(bedrock_data_gas, U256::from(1136)); // Regolith has no added 68 non zero bytes // gas cost = 3 * 16 = 48 - let regolith_data_gas = l1_block_info.data_gas(&input, SpecId::REGOLITH); + let regolith_data_gas = l1_block_info.data_gas(&input, OptimismSpecId::REGOLITH); assert_eq!(regolith_data_gas, U256::from(48)); // Fjord has a minimum compressed size of 100 bytes // gas cost = 100 * 16 = 1600 - let fjord_data_gas = l1_block_info.data_gas(&input, SpecId::FJORD); + let fjord_data_gas = l1_block_info.data_gas(&input, OptimismSpecId::FJORD); assert_eq!(fjord_data_gas, U256::from(1600)); } @@ -292,17 +297,17 @@ mod tests { // gas cost = 3 non-zero * NON_ZERO_BYTE_COST + 2 * ZERO_BYTE_COST + NON_ZERO_BYTE_COST * 68 // gas cost = 3 * 16 + 2 * 4 + 68 * 16 = 1144 let input = bytes!("FA00CA00DE"); - let bedrock_data_gas = l1_block_info.data_gas(&input, SpecId::BEDROCK); + let bedrock_data_gas = l1_block_info.data_gas(&input, OptimismSpecId::BEDROCK); assert_eq!(bedrock_data_gas, U256::from(1144)); // Regolith has no added 68 non zero bytes // gas cost = 3 * 16 + 2 * 4 = 56 - let regolith_data_gas = l1_block_info.data_gas(&input, SpecId::REGOLITH); + let regolith_data_gas = l1_block_info.data_gas(&input, OptimismSpecId::REGOLITH); assert_eq!(regolith_data_gas, U256::from(56)); // Fjord has a minimum compressed size of 100 bytes // gas cost = 100 * 16 = 1600 - let fjord_data_gas = l1_block_info.data_gas(&input, SpecId::FJORD); + let fjord_data_gas = l1_block_info.data_gas(&input, OptimismSpecId::FJORD); assert_eq!(fjord_data_gas, U256::from(1600)); } @@ -316,17 +321,17 @@ mod tests { }; let input = bytes!("FACADE"); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::REGOLITH); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::REGOLITH); assert_eq!(gas_cost, U256::from(1048)); // Zero rollup data gas cost should result in zero let input = bytes!(""); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::REGOLITH); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::REGOLITH); assert_eq!(gas_cost, U256::ZERO); // Deposit transactions with the EIP-2718 type of 0x7F should result in zero let input = bytes!("7FFACADE"); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::REGOLITH); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::REGOLITH); assert_eq!(gas_cost, U256::ZERO); } @@ -345,23 +350,23 @@ mod tests { // = (16 * 3) * (1000 * 16 * 1000 + 1000 * 1000) / (16 * 1e6) // = 51 let input = bytes!("FACADE"); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::ECOTONE); assert_eq!(gas_cost, U256::from(51)); // Zero rollup data gas cost should result in zero let input = bytes!(""); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::ECOTONE); assert_eq!(gas_cost, U256::ZERO); // Deposit transactions with the EIP-2718 type of 0x7F should result in zero let input = bytes!("7FFACADE"); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::ECOTONE); assert_eq!(gas_cost, U256::ZERO); // If the scalars are empty, the bedrock cost function should be used. l1_block_info.empty_scalars = true; let input = bytes!("FACADE"); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::ECOTONE); assert_eq!(gas_cost, U256::from(1048)); } @@ -386,7 +391,7 @@ mod tests { // l1Cost = estimatedSize * l1FeeScaled / 1e12 // = 100e6 * 17 / 1e6 // = 1700 - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::FJORD); assert_eq!(gas_cost, U256::from(1700)); // fastLzSize = 202 @@ -397,17 +402,17 @@ mod tests { // l1Cost = estimatedSize * l1FeeScaled / 1e12 // = 126387400 * 17 / 1e6 // = 2148 - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::FJORD); assert_eq!(gas_cost, U256::from(2148)); // Zero rollup data gas cost should result in zero let input = bytes!(""); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::FJORD); assert_eq!(gas_cost, U256::ZERO); // Deposit transactions with the EIP-2718 type of 0x7F should result in zero let input = bytes!("7FFACADE"); - let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, OptimismSpecId::FJORD); assert_eq!(gas_cost, U256::ZERO); } } diff --git a/crates/revm/src/optimism/result.rs b/crates/revm/src/optimism/result.rs new file mode 100644 index 0000000000..2fc4a8748c --- /dev/null +++ b/crates/revm/src/optimism/result.rs @@ -0,0 +1,100 @@ +use core::fmt::Display; + +use crate::primitives::{EVMError, HaltReason, InvalidTransaction}; + +use super::OptimismChainSpec; + +/// Optimism transaction validation error. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum OptimismInvalidTransaction { + Base(InvalidTransaction), + /// System transactions are not supported post-regolith hardfork. + /// + /// Before the Regolith hardfork, there was a special field in the `Deposit` transaction + /// type that differentiated between `system` and `user` deposit transactions. This field + /// was deprecated in the Regolith hardfork, and this error is thrown if a `Deposit` transaction + /// is found with this field set to `true` after the hardfork activation. + /// + /// In addition, this error is internal, and bubbles up into a [OptimismHaltReason::FailedDeposit] error + /// in the `revm` handler for the consumer to easily handle. This is due to a state transition + /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction + /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and + /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors + /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this + /// case for failed deposit transactions. + DepositSystemTxPostRegolith, + /// Deposit transaction haults bubble up to the global main return handler, wiping state and + /// only increasing the nonce + persisting the mint value. + /// + /// This is a catch-all error for any deposit transaction that is results in a [HaltReason] error + /// post-regolith hardfork. This allows for a consumer to easily handle special cases where + /// a deposit transaction fails during validation, but must still be included in the block. + /// + /// In addition, this error is internal, and bubbles up into a [OptimismHaltReason::FailedDeposit] error + /// in the `revm` handler for the consumer to easily handle. This is due to a state transition + /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction + /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and + /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors + /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this + /// case for failed deposit transactions. + HaltedDepositPostRegolith, + /// L1 block info is missing for a non-deposit transaction. + MissingL1BlockInfo, + /// L1 block info is provided for a deposit transaction. + UnexpectedL1BlockInfo, +} + +impl Display for OptimismInvalidTransaction { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Base(error) => error.fmt(f), + Self::DepositSystemTxPostRegolith => { + write!( + f, + "deposit system transactions post regolith hardfork are not supported" + ) + } + Self::HaltedDepositPostRegolith => { + write!( + f, + "deposit transaction halted post-regolith; error will be bubbled up to main return handler" + ) + } + Self::MissingL1BlockInfo => { + write!(f, "non-deposit transaction is missing L1 block info") + } + Self::UnexpectedL1BlockInfo => { + write!(f, "deposit transaction has unexpected L1 block info") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for OptimismInvalidTransaction {} + +impl From for OptimismInvalidTransaction { + fn from(value: InvalidTransaction) -> Self { + Self::Base(value) + } +} + +impl From for EVMError { + fn from(value: OptimismInvalidTransaction) -> Self { + Self::Transaction(value) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum OptimismHaltReason { + Base(HaltReason), + FailedDeposit, +} + +impl From for OptimismHaltReason { + fn from(value: HaltReason) -> Self { + Self::Base(value) + } +} diff --git a/crates/revm/src/optimism/spec.rs b/crates/revm/src/optimism/spec.rs new file mode 100644 index 0000000000..0bb0c9d267 --- /dev/null +++ b/crates/revm/src/optimism/spec.rs @@ -0,0 +1,791 @@ +use revm_precompile::PrecompileSpecId; + +use crate::primitives::{ChainSpec, Spec, SpecId}; + +use super::{ + env::{OptimismBlock, OptimismTransaction}, + OptimismHaltReason, +}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct OptimismChainSpec; + +impl ChainSpec for OptimismChainSpec { + type Block = OptimismBlock; + type Hardfork = OptimismSpecId; + type HaltReason = OptimismHaltReason; + type Transaction = OptimismTransaction; +} + +/// Specification IDs for the optimism blockchain. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[allow(non_camel_case_types)] +pub enum OptimismSpecId { + FRONTIER = 0, + FRONTIER_THAWING = 1, + HOMESTEAD = 2, + DAO_FORK = 3, + TANGERINE = 4, + SPURIOUS_DRAGON = 5, + BYZANTIUM = 6, + CONSTANTINOPLE = 7, + PETERSBURG = 8, + ISTANBUL = 9, + MUIR_GLACIER = 10, + BERLIN = 11, + LONDON = 12, + ARROW_GLACIER = 13, + GRAY_GLACIER = 14, + MERGE = 15, + BEDROCK = 16, + REGOLITH = 17, + SHANGHAI = 18, + CANYON = 19, + CANCUN = 20, + ECOTONE = 21, + FJORD = 22, + PRAGUE = 23, + PRAGUE_EOF = 24, + #[default] + LATEST = u8::MAX, +} + +impl OptimismSpecId { + /// Returns the `OptimismSpecId` for the given `u8`. + #[inline] + pub fn try_from_u8(spec_id: u8) -> Option { + Self::n(spec_id) + } + + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + pub const fn is_enabled_in(self, other: Self) -> bool { + Self::enabled(self, other) + } + + /// Returns `true` if the given specification ID is enabled in this spec. + #[inline] + pub const fn enabled(our: Self, other: Self) -> bool { + our as u8 >= other as u8 + } + + /// Converts the `OptimismSpecId` into a `SpecId`. + const fn into_eth_spec_id(self) -> SpecId { + match self { + OptimismSpecId::FRONTIER => SpecId::FRONTIER, + OptimismSpecId::FRONTIER_THAWING => SpecId::FRONTIER_THAWING, + OptimismSpecId::HOMESTEAD => SpecId::HOMESTEAD, + OptimismSpecId::DAO_FORK => SpecId::DAO_FORK, + OptimismSpecId::TANGERINE => SpecId::TANGERINE, + OptimismSpecId::SPURIOUS_DRAGON => SpecId::SPURIOUS_DRAGON, + OptimismSpecId::BYZANTIUM => SpecId::BYZANTIUM, + OptimismSpecId::CONSTANTINOPLE => SpecId::CONSTANTINOPLE, + OptimismSpecId::PETERSBURG => SpecId::PETERSBURG, + OptimismSpecId::ISTANBUL => SpecId::ISTANBUL, + OptimismSpecId::MUIR_GLACIER => SpecId::MUIR_GLACIER, + OptimismSpecId::BERLIN => SpecId::BERLIN, + OptimismSpecId::LONDON => SpecId::LONDON, + OptimismSpecId::ARROW_GLACIER => SpecId::ARROW_GLACIER, + OptimismSpecId::GRAY_GLACIER => SpecId::GRAY_GLACIER, + OptimismSpecId::MERGE | OptimismSpecId::BEDROCK | OptimismSpecId::REGOLITH => { + SpecId::MERGE + } + OptimismSpecId::SHANGHAI | OptimismSpecId::CANYON => SpecId::SHANGHAI, + OptimismSpecId::CANCUN | OptimismSpecId::ECOTONE | OptimismSpecId::FJORD => { + SpecId::CANCUN + } + OptimismSpecId::PRAGUE => SpecId::PRAGUE, + OptimismSpecId::PRAGUE_EOF => SpecId::PRAGUE_EOF, + OptimismSpecId::LATEST => SpecId::LATEST, + } + } +} + +impl From for SpecId { + fn from(value: OptimismSpecId) -> Self { + value.into_eth_spec_id() + } +} + +impl From for OptimismSpecId { + fn from(value: SpecId) -> Self { + match value { + SpecId::FRONTIER => Self::FRONTIER, + SpecId::FRONTIER_THAWING => Self::FRONTIER_THAWING, + SpecId::HOMESTEAD => Self::HOMESTEAD, + SpecId::DAO_FORK => Self::DAO_FORK, + SpecId::TANGERINE => Self::TANGERINE, + SpecId::SPURIOUS_DRAGON => Self::SPURIOUS_DRAGON, + SpecId::BYZANTIUM => Self::BYZANTIUM, + SpecId::CONSTANTINOPLE => Self::CONSTANTINOPLE, + SpecId::PETERSBURG => Self::PETERSBURG, + SpecId::ISTANBUL => Self::ISTANBUL, + SpecId::MUIR_GLACIER => Self::MUIR_GLACIER, + SpecId::BERLIN => Self::BERLIN, + SpecId::LONDON => Self::LONDON, + SpecId::ARROW_GLACIER => Self::ARROW_GLACIER, + SpecId::GRAY_GLACIER => Self::GRAY_GLACIER, + SpecId::MERGE => Self::MERGE, + SpecId::SHANGHAI => Self::SHANGHAI, + SpecId::CANCUN => Self::CANCUN, + SpecId::PRAGUE => Self::PRAGUE, + SpecId::PRAGUE_EOF => Self::PRAGUE_EOF, + SpecId::LATEST => Self::LATEST, + } + } +} + +impl From for PrecompileSpecId { + fn from(value: OptimismSpecId) -> Self { + PrecompileSpecId::from_spec_id(value.into_eth_spec_id()) + } +} + +impl From<&str> for OptimismSpecId { + fn from(name: &str) -> Self { + match name { + "Frontier" => Self::FRONTIER, + "Homestead" => Self::HOMESTEAD, + "Tangerine" => Self::TANGERINE, + "Spurious" => Self::SPURIOUS_DRAGON, + "Byzantium" => Self::BYZANTIUM, + "Constantinople" => Self::CONSTANTINOPLE, + "Petersburg" => Self::PETERSBURG, + "Istanbul" => Self::ISTANBUL, + "MuirGlacier" => Self::MUIR_GLACIER, + "Berlin" => Self::BERLIN, + "London" => Self::LONDON, + "Merge" => Self::MERGE, + "Shanghai" => Self::SHANGHAI, + "Cancun" => Self::CANCUN, + "Prague" => Self::PRAGUE, + "PragueEOF" => Self::PRAGUE_EOF, + "Bedrock" => Self::BEDROCK, + "Regolith" => Self::REGOLITH, + "Canyon" => Self::CANYON, + "Ecotone" => Self::ECOTONE, + "Fjord" => Self::FJORD, + _ => Self::LATEST, + } + } +} + +impl From for &'static str { + fn from(value: OptimismSpecId) -> Self { + match value { + OptimismSpecId::FRONTIER + | OptimismSpecId::FRONTIER_THAWING + | OptimismSpecId::HOMESTEAD + | OptimismSpecId::DAO_FORK + | OptimismSpecId::TANGERINE + | OptimismSpecId::SPURIOUS_DRAGON + | OptimismSpecId::BYZANTIUM + | OptimismSpecId::CONSTANTINOPLE + | OptimismSpecId::PETERSBURG + | OptimismSpecId::ISTANBUL + | OptimismSpecId::MUIR_GLACIER + | OptimismSpecId::BERLIN + | OptimismSpecId::LONDON + | OptimismSpecId::ARROW_GLACIER + | OptimismSpecId::GRAY_GLACIER + | OptimismSpecId::MERGE + | OptimismSpecId::SHANGHAI + | OptimismSpecId::CANCUN + | OptimismSpecId::PRAGUE + | OptimismSpecId::PRAGUE_EOF => value.into_eth_spec_id().into(), + OptimismSpecId::BEDROCK => "Bedrock", + OptimismSpecId::REGOLITH => "Regolith", + OptimismSpecId::CANYON => "Canyon", + OptimismSpecId::ECOTONE => "Ecotone", + OptimismSpecId::FJORD => "Fjord", + OptimismSpecId::LATEST => "Latest", + } + } +} + +pub trait OptimismSpec: Spec + Sized + 'static { + /// The specification ID for optimism. + const OPTIMISM_SPEC_ID: OptimismSpecId; + + /// Returns whether the provided `OptimismSpec` is enabled by this spec. + #[inline] + fn optimism_enabled(spec_id: OptimismSpecId) -> bool { + OptimismSpecId::enabled(Self::OPTIMISM_SPEC_ID, spec_id) + } +} + +macro_rules! spec { + ($spec_id:ident, $spec_name:ident) => { + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $spec_name; + + impl OptimismSpec for $spec_name { + const OPTIMISM_SPEC_ID: OptimismSpecId = OptimismSpecId::$spec_id; + } + + impl Spec for $spec_name { + const SPEC_ID: SpecId = $spec_name::OPTIMISM_SPEC_ID.into_eth_spec_id(); + } + }; +} + +spec!(FRONTIER, FrontierSpec); +// FRONTIER_THAWING no EVM spec change +spec!(HOMESTEAD, HomesteadSpec); +// DAO_FORK no EVM spec change +spec!(TANGERINE, TangerineSpec); +spec!(SPURIOUS_DRAGON, SpuriousDragonSpec); +spec!(BYZANTIUM, ByzantiumSpec); +// CONSTANTINOPLE was overridden with PETERSBURG +spec!(PETERSBURG, PetersburgSpec); +spec!(ISTANBUL, IstanbulSpec); +// MUIR_GLACIER no EVM spec change +spec!(BERLIN, BerlinSpec); +spec!(LONDON, LondonSpec); +// ARROW_GLACIER no EVM spec change +// GRAY_GLACIER no EVM spec change +spec!(MERGE, MergeSpec); +spec!(SHANGHAI, ShanghaiSpec); +spec!(CANCUN, CancunSpec); +spec!(PRAGUE, PragueSpec); +spec!(PRAGUE_EOF, PragueEofSpec); + +spec!(LATEST, LatestSpec); + +// Optimism Hardforks +spec!(BEDROCK, BedrockSpec); +spec!(REGOLITH, RegolithSpec); +spec!(CANYON, CanyonSpec); +spec!(ECOTONE, EcotoneSpec); +spec!(FJORD, FjordSpec); + +#[macro_export] +macro_rules! optimism_spec_to_generic { + ($spec_id:expr, $e:expr) => {{ + // We are transitioning from var to generic spec. + match $spec_id { + $crate::optimism::OptimismSpecId::FRONTIER + | $crate::optimism::OptimismSpecId::FRONTIER_THAWING => { + use $crate::optimism::FrontierSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::HOMESTEAD + | $crate::optimism::OptimismSpecId::DAO_FORK => { + use $crate::optimism::HomesteadSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::TANGERINE => { + use $crate::optimism::TangerineSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::SPURIOUS_DRAGON => { + use $crate::optimism::SpuriousDragonSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::BYZANTIUM => { + use $crate::optimism::ByzantiumSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::PETERSBURG + | $crate::optimism::OptimismSpecId::CONSTANTINOPLE => { + use $crate::optimism::PetersburgSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::ISTANBUL + | $crate::optimism::OptimismSpecId::MUIR_GLACIER => { + use $crate::optimism::IstanbulSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::BERLIN => { + use $crate::optimism::BerlinSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::LONDON + | $crate::optimism::OptimismSpecId::ARROW_GLACIER + | $crate::optimism::OptimismSpecId::GRAY_GLACIER => { + use $crate::optimism::LondonSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::MERGE => { + use $crate::optimism::MergeSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::SHANGHAI => { + use $crate::optimism::ShanghaiSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::CANCUN => { + use $crate::optimism::CancunSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::LATEST => { + use $crate::optimism::LatestSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::PRAGUE => { + use $crate::optimism::PragueSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::PRAGUE_EOF => { + use $crate::optimism::PragueEofSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::BEDROCK => { + use $crate::optimism::BedrockSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::REGOLITH => { + use $crate::optimism::RegolithSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::CANYON => { + use $crate::optimism::CanyonSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::ECOTONE => { + use $crate::optimism::EcotoneSpec as SPEC; + $e + } + $crate::optimism::OptimismSpecId::FJORD => { + use $crate::optimism::FjordSpec as SPEC; + $e + } + } + }}; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn optimism_spec_to_generic() { + optimism_spec_to_generic!( + OptimismSpecId::FRONTIER, + assert_eq!(SPEC::SPEC_ID, SpecId::FRONTIER) + ); + optimism_spec_to_generic!( + OptimismSpecId::FRONTIER_THAWING, + assert_eq!(SPEC::SPEC_ID, SpecId::FRONTIER) + ); + optimism_spec_to_generic!( + OptimismSpecId::HOMESTEAD, + assert_eq!(SPEC::SPEC_ID, SpecId::HOMESTEAD) + ); + optimism_spec_to_generic!( + OptimismSpecId::DAO_FORK, + assert_eq!(SPEC::SPEC_ID, SpecId::HOMESTEAD) + ); + optimism_spec_to_generic!( + OptimismSpecId::TANGERINE, + assert_eq!(SPEC::SPEC_ID, SpecId::TANGERINE) + ); + optimism_spec_to_generic!( + OptimismSpecId::SPURIOUS_DRAGON, + assert_eq!(SPEC::SPEC_ID, SpecId::SPURIOUS_DRAGON) + ); + optimism_spec_to_generic!( + OptimismSpecId::BYZANTIUM, + assert_eq!(SPEC::SPEC_ID, SpecId::BYZANTIUM) + ); + optimism_spec_to_generic!( + OptimismSpecId::CONSTANTINOPLE, + assert_eq!(SPEC::SPEC_ID, SpecId::PETERSBURG) + ); + optimism_spec_to_generic!( + OptimismSpecId::PETERSBURG, + assert_eq!(SPEC::SPEC_ID, SpecId::PETERSBURG) + ); + optimism_spec_to_generic!( + OptimismSpecId::ISTANBUL, + assert_eq!(SPEC::SPEC_ID, SpecId::ISTANBUL) + ); + optimism_spec_to_generic!( + OptimismSpecId::MUIR_GLACIER, + assert_eq!(SPEC::SPEC_ID, SpecId::ISTANBUL) + ); + optimism_spec_to_generic!( + OptimismSpecId::BERLIN, + assert_eq!(SPEC::SPEC_ID, SpecId::BERLIN) + ); + optimism_spec_to_generic!( + OptimismSpecId::LONDON, + assert_eq!(SPEC::SPEC_ID, SpecId::LONDON) + ); + optimism_spec_to_generic!( + OptimismSpecId::ARROW_GLACIER, + assert_eq!(SPEC::SPEC_ID, SpecId::LONDON) + ); + optimism_spec_to_generic!( + OptimismSpecId::GRAY_GLACIER, + assert_eq!(SPEC::SPEC_ID, SpecId::LONDON) + ); + optimism_spec_to_generic!( + OptimismSpecId::MERGE, + assert_eq!(SPEC::SPEC_ID, SpecId::MERGE) + ); + optimism_spec_to_generic!( + OptimismSpecId::BEDROCK, + assert_eq!(SPEC::SPEC_ID, SpecId::MERGE) + ); + optimism_spec_to_generic!( + OptimismSpecId::REGOLITH, + assert_eq!(SPEC::SPEC_ID, SpecId::MERGE) + ); + optimism_spec_to_generic!( + OptimismSpecId::SHANGHAI, + assert_eq!(SPEC::SPEC_ID, SpecId::SHANGHAI) + ); + optimism_spec_to_generic!( + OptimismSpecId::CANYON, + assert_eq!(SPEC::SPEC_ID, SpecId::SHANGHAI) + ); + optimism_spec_to_generic!( + OptimismSpecId::CANCUN, + assert_eq!(SPEC::SPEC_ID, SpecId::CANCUN) + ); + optimism_spec_to_generic!( + OptimismSpecId::ECOTONE, + assert_eq!(SPEC::SPEC_ID, SpecId::CANCUN) + ); + optimism_spec_to_generic!( + OptimismSpecId::FJORD, + assert_eq!(SPEC::SPEC_ID, SpecId::CANCUN) + ); + optimism_spec_to_generic!( + OptimismSpecId::PRAGUE, + assert_eq!(SPEC::SPEC_ID, SpecId::PRAGUE) + ); + optimism_spec_to_generic!( + OptimismSpecId::LATEST, + assert_eq!(SPEC::SPEC_ID, SpecId::LATEST) + ); + + optimism_spec_to_generic!( + OptimismSpecId::FRONTIER, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::FRONTIER) + ); + optimism_spec_to_generic!( + OptimismSpecId::FRONTIER_THAWING, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::FRONTIER) + ); + optimism_spec_to_generic!( + OptimismSpecId::HOMESTEAD, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::HOMESTEAD) + ); + optimism_spec_to_generic!( + OptimismSpecId::DAO_FORK, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::HOMESTEAD) + ); + optimism_spec_to_generic!( + OptimismSpecId::TANGERINE, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::TANGERINE) + ); + optimism_spec_to_generic!( + OptimismSpecId::SPURIOUS_DRAGON, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::SPURIOUS_DRAGON) + ); + optimism_spec_to_generic!( + OptimismSpecId::BYZANTIUM, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::BYZANTIUM) + ); + optimism_spec_to_generic!( + OptimismSpecId::CONSTANTINOPLE, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::PETERSBURG) + ); + optimism_spec_to_generic!( + OptimismSpecId::PETERSBURG, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::PETERSBURG) + ); + optimism_spec_to_generic!( + OptimismSpecId::ISTANBUL, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::ISTANBUL) + ); + optimism_spec_to_generic!( + OptimismSpecId::MUIR_GLACIER, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::ISTANBUL) + ); + optimism_spec_to_generic!( + OptimismSpecId::BERLIN, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::BERLIN) + ); + optimism_spec_to_generic!( + OptimismSpecId::LONDON, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::LONDON) + ); + optimism_spec_to_generic!( + OptimismSpecId::ARROW_GLACIER, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::LONDON) + ); + optimism_spec_to_generic!( + OptimismSpecId::GRAY_GLACIER, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::LONDON) + ); + optimism_spec_to_generic!( + OptimismSpecId::MERGE, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::MERGE) + ); + optimism_spec_to_generic!( + OptimismSpecId::BEDROCK, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::BEDROCK) + ); + optimism_spec_to_generic!( + OptimismSpecId::REGOLITH, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::REGOLITH) + ); + optimism_spec_to_generic!( + OptimismSpecId::SHANGHAI, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::SHANGHAI) + ); + optimism_spec_to_generic!( + OptimismSpecId::CANYON, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::CANYON) + ); + optimism_spec_to_generic!( + OptimismSpecId::CANCUN, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::CANCUN) + ); + optimism_spec_to_generic!( + OptimismSpecId::ECOTONE, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::ECOTONE) + ); + optimism_spec_to_generic!( + OptimismSpecId::FJORD, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::FJORD) + ); + optimism_spec_to_generic!( + OptimismSpecId::PRAGUE, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::PRAGUE) + ); + optimism_spec_to_generic!( + OptimismSpecId::PRAGUE_EOF, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::PRAGUE_EOF) + ); + optimism_spec_to_generic!( + OptimismSpecId::LATEST, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::LATEST) + ); + } + + #[test] + fn test_bedrock_post_merge_hardforks() { + assert!(BedrockSpec::optimism_enabled(OptimismSpecId::MERGE)); + assert!(!BedrockSpec::optimism_enabled(OptimismSpecId::SHANGHAI)); + assert!(!BedrockSpec::optimism_enabled(OptimismSpecId::CANCUN)); + assert!(!BedrockSpec::optimism_enabled(OptimismSpecId::LATEST)); + assert!(BedrockSpec::optimism_enabled(OptimismSpecId::BEDROCK)); + assert!(!BedrockSpec::optimism_enabled(OptimismSpecId::REGOLITH)); + } + + #[test] + fn test_regolith_post_merge_hardforks() { + assert!(RegolithSpec::optimism_enabled(OptimismSpecId::MERGE)); + assert!(!RegolithSpec::optimism_enabled(OptimismSpecId::SHANGHAI)); + assert!(!RegolithSpec::optimism_enabled(OptimismSpecId::CANCUN)); + assert!(!RegolithSpec::optimism_enabled(OptimismSpecId::LATEST)); + assert!(RegolithSpec::optimism_enabled(OptimismSpecId::BEDROCK)); + assert!(RegolithSpec::optimism_enabled(OptimismSpecId::REGOLITH)); + } + + #[test] + fn test_bedrock_post_merge_hardforks_spec_id() { + assert!(OptimismSpecId::enabled( + OptimismSpecId::BEDROCK, + OptimismSpecId::MERGE + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::BEDROCK, + OptimismSpecId::SHANGHAI + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::BEDROCK, + OptimismSpecId::CANCUN + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::BEDROCK, + OptimismSpecId::LATEST + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::BEDROCK, + OptimismSpecId::BEDROCK + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::BEDROCK, + OptimismSpecId::REGOLITH + )); + } + + #[test] + fn test_regolith_post_merge_hardforks_spec_id() { + assert!(OptimismSpecId::enabled( + OptimismSpecId::REGOLITH, + OptimismSpecId::MERGE + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::REGOLITH, + OptimismSpecId::SHANGHAI + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::REGOLITH, + OptimismSpecId::CANCUN + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::REGOLITH, + OptimismSpecId::LATEST + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::REGOLITH, + OptimismSpecId::BEDROCK + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::REGOLITH, + OptimismSpecId::REGOLITH + )); + } + + #[test] + fn test_canyon_post_merge_hardforks() { + assert!(CanyonSpec::optimism_enabled(OptimismSpecId::MERGE)); + assert!(CanyonSpec::optimism_enabled(OptimismSpecId::SHANGHAI)); + assert!(!CanyonSpec::optimism_enabled(OptimismSpecId::CANCUN)); + assert!(!CanyonSpec::optimism_enabled(OptimismSpecId::LATEST)); + assert!(CanyonSpec::optimism_enabled(OptimismSpecId::BEDROCK)); + assert!(CanyonSpec::optimism_enabled(OptimismSpecId::REGOLITH)); + assert!(CanyonSpec::optimism_enabled(OptimismSpecId::CANYON)); + } + + #[test] + fn test_canyon_post_merge_hardforks_spec_id() { + assert!(OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::MERGE + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::SHANGHAI + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::CANCUN + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::LATEST + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::BEDROCK + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::REGOLITH + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::CANYON, + OptimismSpecId::CANYON + )); + } + + #[test] + fn test_ecotone_post_merge_hardforks() { + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::MERGE)); + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::SHANGHAI)); + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::CANCUN)); + assert!(!EcotoneSpec::optimism_enabled(OptimismSpecId::LATEST)); + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::BEDROCK)); + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::REGOLITH)); + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::CANYON)); + assert!(EcotoneSpec::optimism_enabled(OptimismSpecId::ECOTONE)); + } + + #[test] + fn test_ecotone_post_merge_hardforks_spec_id() { + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::MERGE + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::SHANGHAI + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::CANCUN + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::LATEST + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::BEDROCK + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::REGOLITH + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::CANYON + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::ECOTONE, + OptimismSpecId::ECOTONE + )); + } + + #[test] + fn test_fjord_post_merge_hardforks() { + assert!(FjordSpec::optimism_enabled(OptimismSpecId::MERGE)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::SHANGHAI)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::CANCUN)); + assert!(!FjordSpec::optimism_enabled(OptimismSpecId::LATEST)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::BEDROCK)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::REGOLITH)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::CANYON)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::ECOTONE)); + assert!(FjordSpec::optimism_enabled(OptimismSpecId::FJORD)); + } + + #[test] + fn test_fjord_post_merge_hardforks_spec_id() { + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::MERGE + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::SHANGHAI + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::CANCUN + )); + assert!(!OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::LATEST + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::BEDROCK + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::REGOLITH + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::CANYON + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::ECOTONE + )); + assert!(OptimismSpecId::enabled( + OptimismSpecId::FJORD, + OptimismSpecId::FJORD + )); + } +} diff --git a/examples/db_by_ref.rs b/examples/db_by_ref.rs index 9e3615400c..d866899d71 100644 --- a/examples/db_by_ref.rs +++ b/examples/db_by_ref.rs @@ -3,7 +3,7 @@ use revm::{ handler::register::HandleRegister, inspector_handle_register, inspectors::{NoOpInspector, TracerEip3155}, - primitives::ResultAndState, + primitives::{EthChainSpec, ResultAndState}, DatabaseCommit, DatabaseRef, Evm, }; use std::error::Error; @@ -23,8 +23,8 @@ where fn run_transaction( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, -) -> anyhow::Result<(ResultAndState, DB)> { + register_handles_fn: HandleRegister>, +) -> anyhow::Result<(ResultAndState, DB)> { let mut evm = Evm::builder() .with_ref_db(db) .with_external_context(ext) @@ -38,7 +38,7 @@ fn run_transaction( fn run_transaction_and_commit_with_ext( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, + register_handles_fn: HandleRegister>, ) -> anyhow::Result<()> { // To circumvent borrow checker issues, we need to move the database into the // transaction and return it after the transaction is done. From 6145d398b542f868123687994d7bbbbae3954eb4 Mon Sep 17 00:00:00 2001 From: Wodann Date: Tue, 18 Jun 2024 18:24:25 +0000 Subject: [PATCH 02/59] refactor: rename Transaction::transact_to and clarify docs --- crates/interpreter/src/interpreter/contract.rs | 2 +- .../src/interpreter_action/call_inputs.rs | 2 +- .../src/interpreter_action/create_inputs.rs | 2 +- crates/primitives/src/env.rs | 6 +++--- crates/primitives/src/transaction.rs | 14 +++++++------- crates/revm/src/evm.rs | 2 +- crates/revm/src/handler/mainnet/pre_execution.rs | 2 +- crates/revm/src/handler/mainnet/validation.rs | 2 +- crates/revm/src/optimism/env.rs | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 21c4080792..50ed5bb226 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -60,7 +60,7 @@ impl Contract { bytecode: Bytecode, hash: Option, ) -> Self { - let contract_address = match env.tx.transact_to() { + let contract_address = match env.tx.kind() { TxKind::Call(caller) => *caller, TxKind::Create => Address::ZERO, }; diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index b71e9c14e0..d5ad291485 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -49,7 +49,7 @@ impl CallInputs { /// /// Returns `None` if the transaction is not a call. pub fn new(tx_env: &impl Transaction, gas_limit: u64) -> Option { - let TxKind::Call(target_address) = *tx_env.transact_to() else { + let TxKind::Call(target_address) = *tx_env.kind() else { return None; }; Some(CallInputs { diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index cafd2caa07..151df91d21 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -23,7 +23,7 @@ pub struct CreateInputs { impl CreateInputs { /// Creates new create inputs. pub fn new(tx_env: &impl Transaction, gas_limit: u64) -> Option { - let TxKind::Create = tx_env.transact_to() else { + let TxKind::Create = tx_env.kind() else { return None; }; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 9ab9e57d9c..a3b52fb89d 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -134,7 +134,7 @@ impl Env { } // EIP-3860: Limit and meter initcode - if SPEC::enabled(SpecId::SHANGHAI) && self.tx.transact_to().is_create() { + if SPEC::enabled(SpecId::SHANGHAI) && self.tx.kind().is_create() { let max_initcode_size = self .cfg .limit_contract_code_size @@ -169,7 +169,7 @@ impl Env { // that it MUST NOT be nil and therefore must always represent // a 20-byte address. This means that blob transactions cannot // have the form of a create transaction. - if self.tx.transact_to().is_create() { + if self.tx.kind().is_create() { return Err(InvalidTransaction::BlobCreateTransaction); } @@ -616,7 +616,7 @@ impl Transaction for TxEnv { } #[inline] - fn transact_to(&self) -> &TransactTo { + fn kind(&self) -> &TransactTo { &self.transact_to } diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index b0523cc5a8..225c1e96fc 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -19,15 +19,15 @@ pub trait Transaction: Clone + Debug + Default + PartialEq + Eq { /// Caller aka Author aka transaction signer. fn caller(&self) -> &Address; - /// The gas limit of the transaction. + /// The maximum amount of gas the transaction can use. fn gas_limit(&self) -> u64; - /// The gas price of the transaction. + /// The gas price the sender is willing to pay. fn gas_price(&self) -> &U256; - /// The destination of the transaction. - fn transact_to(&self) -> &TxKind; - /// The value sent to `transact_to`. + /// Returns what kind of transaction this is. + fn kind(&self) -> &TxKind; + /// The value sent to the receiver of `TxKind::Call`. fn value(&self) -> &U256; - /// The data of the transaction. + /// Returns the input data of the transaction. fn data(&self) -> &Bytes; /// The nonce of the transaction. /// @@ -58,7 +58,7 @@ pub trait Transaction: Clone + Debug + Default + PartialEq + Eq { /// /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 fn blob_hashes(&self) -> &[B256]; - /// The max fee per blob gas. + /// The maximum fee per blob gas the sender is willing to pay. /// /// Incorporated as part of the Cancun upgrade via [EIP-4844]. /// diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 7f30d6cb23..7d7e9835fc 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -343,7 +343,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { let exec = self.handler.execution(); // call inner handling of call/create - let first_frame_or_result = match ctx.evm.env.tx.transact_to() { + let first_frame_or_result = match ctx.evm.env.tx.kind() { TxKind::Call(_) => exec.call( ctx, CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index da95e91417..9675b34f93 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -143,7 +143,7 @@ pub fn deduct_caller_inner( caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost); // bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. - if env.tx.transact_to().is_call() { + if env.tx.kind().is_call() { // Nonce is already checked caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index 9ac16adc02..c337bb0bf3 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -44,7 +44,7 @@ pub fn validate_initial_tx_gas( env: &Env, ) -> Result> { let input = &env.tx.data(); - let is_create = env.tx.transact_to().is_create(); + let is_create = env.tx.kind().is_create(); let access_list = &env.tx.access_list(); let authorization_list_num = env .tx diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index 4c4c29c59e..372e5547db 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -129,8 +129,8 @@ impl Transaction for OptimismTransaction { self.base.gas_price() } - fn transact_to(&self) -> &TransactTo { - self.base.transact_to() + fn kind(&self) -> &TransactTo { + self.base.kind() } fn value(&self) -> &U256 { From 7b950c73ccfc40abdde28cc2aa675b002a4ccdd3 Mon Sep 17 00:00:00 2001 From: Wodann Date: Tue, 18 Jun 2024 20:23:16 +0000 Subject: [PATCH 03/59] refactor: remove trait bounds on Transaction super trait --- Cargo.lock | 14 ++ crates/interpreter/Cargo.toml | 1 + crates/interpreter/src/host/dummy.rs | 34 +++- crates/interpreter/src/instruction_result.rs | 6 +- .../interpreter/src/interpreter/contract.rs | 2 +- crates/primitives/Cargo.toml | 1 + crates/primitives/src/block.rs | 3 +- crates/primitives/src/chain_spec.rs | 19 +- crates/primitives/src/env.rs | 29 ++- crates/primitives/src/result.rs | 44 ++-- crates/primitives/src/transaction.rs | 19 +- crates/revm/Cargo.toml | 1 + crates/revm/src/builder.rs | 48 +++-- crates/revm/src/context.rs | 23 ++- .../revm/src/context/context_precompiles.rs | 19 +- crates/revm/src/context/evm_context.rs | 50 +++-- crates/revm/src/context/inner_evm_context.rs | 25 +-- crates/revm/src/evm.rs | 49 ++++- crates/revm/src/handler.rs | 33 ++- crates/revm/src/handler/cfg.rs | 29 ++- .../src/handler/handle_types/execution.rs | 189 ++++++++++++++---- .../handler/handle_types/post_execution.rs | 59 +++++- .../src/handler/handle_types/pre_execution.rs | 29 ++- .../src/handler/handle_types/validation.rs | 65 +++++- crates/revm/src/handler/mainnet/execution.rs | 90 +++++++-- .../src/handler/mainnet/post_execution.rs | 42 +++- .../revm/src/handler/mainnet/pre_execution.rs | 18 +- crates/revm/src/handler/mainnet/validation.rs | 38 +++- crates/revm/src/inspector/handler_register.rs | 12 +- crates/revm/src/optimism/env.rs | 10 +- crates/revm/src/optimism/handler_register.rs | 19 +- crates/revm/src/optimism/result.rs | 4 +- 32 files changed, 773 insertions(+), 251 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d7a0ba379..4e12676946 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1079,6 +1079,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -3014,6 +3025,7 @@ dependencies = [ "anyhow", "auto_impl", "criterion", + "derive-where", "dyn-clone", "enumn", "ethers-contract", @@ -3034,6 +3046,7 @@ name = "revm-interpreter" version = "8.1.0" dependencies = [ "bincode", + "derive-where", "paste", "phf", "revm-primitives", @@ -3079,6 +3092,7 @@ dependencies = [ "bitvec", "c-kzg", "cfg-if", + "derive-where", "derive_more", "dyn-clone", "enumn", diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 8b97e9d3db..162c51190c 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -24,6 +24,7 @@ all = "warn" [dependencies] revm-primitives = { path = "../primitives", version = "7.1.0", default-features = false } +derive-where = { version = "1.2.7", default-features = false } paste = { version = "1.0", optional = true } phf = { version = "0.11", default-features = false, optional = true, features = [ "macros", diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 9ee85d1b65..d7772c621f 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -4,26 +4,33 @@ use crate::{ }, Host, SStoreResult, SelfDestructResult, }; +use core::fmt::Debug; use std::vec::Vec; use super::LoadAccountResult; /// A dummy [Host] implementation. -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct DummyHost { +#[derive(Clone, Debug)] +pub struct DummyHost +where + ChainSpecT: ChainSpec, +{ pub env: Env, pub storage: HashMap, pub transient_storage: HashMap, pub log: Vec, } -impl DummyHost { +impl DummyHost +where + ChainSpecT: ChainSpec, +{ /// Create a new dummy host with the given [`Env`]. #[inline] pub fn new(env: Env) -> Self { Self { env, - ..Default::default() + ..DummyHost::default() } } @@ -35,7 +42,24 @@ impl DummyHost { } } -impl Host for DummyHost { +impl Default for DummyHost +where + ChainSpecT: ChainSpec, +{ + fn default() -> Self { + Self { + env: Env::default(), + storage: HashMap::new(), + transient_storage: HashMap::new(), + log: Vec::new(), + } + } +} + +impl Host for DummyHost +where + ChainSpecT: ChainSpec, +{ type ChainSpecT = ChainSpecT; #[inline] diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index 0e3871c474..910e086685 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -1,3 +1,6 @@ +use core::fmt::Debug; + +use derive_where::derive_where; use revm_primitives::ChainSpec; use crate::primitives::{HaltReason, OutOfGasError, SuccessReason}; @@ -209,7 +212,8 @@ pub enum InternalResult { InvalidExtDelegateCallTarget, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive_where(Debug; ChainSpecT::HaltReason)] pub enum SuccessOrHalt { Success(SuccessReason), Revert, diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 50ed5bb226..9243d04892 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -64,7 +64,7 @@ impl Contract { TxKind::Call(caller) => *caller, TxKind::Create => Address::ZERO, }; - let bytecode_address = match env.tx.transact_to() { + let bytecode_address = match env.tx.kind() { TxKind::Call(caller) => Some(*caller), TxKind::Create => None, }; diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index d99c0a835a..0a3832ff44 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -43,6 +43,7 @@ kzg-rs = { version = "0.1", default-features = false, features = [ # utility enumn = "0.1" derive_more = { version = "0.99", optional = true } +derive-where = { version = "1.2.7", default-features = false } cfg-if = "1" dyn-clone = "1.0" diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index ac08ac24b4..1a5003acb4 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -1,8 +1,7 @@ use crate::{Address, BlobExcessGasAndPrice, B256, U256}; -use core::fmt::Debug; /// Trait for retrieving block information required for execution. -pub trait Block: Clone + Debug + Default + PartialEq + Eq { +pub trait Block { /// The number of ancestor blocks of this block (block height). fn number(&self) -> &U256; diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index fe4b6d508b..52566c5983 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -32,12 +32,25 @@ cfg_if! { } } -pub trait ChainSpec: Clone + Debug + Default + Sized + 'static { +pub trait TransactionValidation { + cfg_if! { + if #[cfg(feature = "std")] { + /// An error that occurs when validating a transaction. + type ValidationError: Debug + std::error::Error; + } else { + /// An error that occurs when validating a transaction. + type ValidationError: Debug; + } + } +} + +pub trait ChainSpec: Sized + 'static { /// The type that contains all block information. - type Block: Block; + type Block: Block + Clone + Debug + Default + PartialEq + Eq; /// The type that contains all transaction information. - type Transaction: Transaction; + type Transaction: Transaction + TransactionValidation; + // Clone + Debug + Default + PartialEq + Eq /// The type that enumerates the chain's hardforks. type Hardfork: HardforkTrait; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index a3b52fb89d..03b2fc6953 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -6,17 +6,20 @@ pub use eip7702::{ use crate::{ block, calc_blob_gasprice, transaction, AccessListItem, Account, Address, Block, Bytes, - ChainSpec, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, B256, KECCAK_EMPTY, - MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, + ChainSpec, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, + B256, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, + VERSIONED_HASH_VERSION_KZG, }; use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; +use core::fmt::Debug; use core::hash::Hash; +use derive_where::derive_where; use std::boxed::Box; use std::vec::Vec; /// EVM environment configuration. -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive_where(Clone, Debug, Default; ChainSpecT::Transaction)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Env { /// Configuration of the EVM itself. @@ -28,12 +31,6 @@ pub struct Env { } impl Env { - /// Resets environment to default values. - #[inline] - pub fn clear(&mut self) { - *self = Self::default(); - } - /// Create boxed [Env]. #[inline] pub fn boxed(cfg: CfgEnv, block: ChainSpecT::Block, tx: ChainSpecT::Transaction) -> Box { @@ -269,6 +266,14 @@ impl Env { } } +impl> Env { + /// Resets environment to default values. + #[inline] + pub fn clear(&mut self) { + *self = Self::default(); + } +} + /// EVM configuration. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, Eq, PartialEq)] @@ -598,8 +603,6 @@ pub struct TxEnv { } impl Transaction for TxEnv { - type TransactionValidationError = InvalidTransaction; - #[inline] fn caller(&self) -> &Address { &self.caller @@ -666,6 +669,10 @@ impl Transaction for TxEnv { } } +impl TransactionValidation for TxEnv { + type ValidationError = InvalidTransaction; +} + pub enum TxType { Legacy, Eip1559, diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index fddad74a8b..01dce7a6dc 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,5 +1,5 @@ -use crate::{Address, Bytes, ChainSpec, EthChainSpec, EvmState, Log, Transaction, U256}; -use core::fmt; +use crate::{Address, Bytes, ChainSpec, EvmState, Log, TransactionValidation, U256}; +use core::fmt::{self, Debug}; use std::{boxed::Box, string::String, vec::Vec}; /// Result of EVM execution. @@ -7,8 +7,13 @@ pub type EVMResult = EVMResultGeneric, ChainSpecT, DBError>; /// Generic result of EVM execution. Used to represent error and generic output. -pub type EVMResultGeneric = - core::result::Result>; +pub type EVMResultGeneric = core::result::Result< + T, + EVMError< + DBError, + <::Transaction as TransactionValidation>::ValidationError, + >, +>; #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -138,10 +143,9 @@ impl Output { /// Main EVM error. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum EVMError { +pub enum EVMError { /// Transaction validation error. - Transaction(::TransactionValidationError), + Transaction(TransactionValidationErrorT), /// Header validation error. Header(InvalidHeader), /// Database error. @@ -154,9 +158,9 @@ pub enum EVMError { Precompile(String), } -impl EVMError { +impl EVMError { /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged. - pub fn map_db_err(self, op: F) -> EVMError + pub fn map_db_err(self, op: F) -> EVMError where F: FnOnce(DBError) -> E, { @@ -171,12 +175,11 @@ impl EVMError { } #[cfg(feature = "std")] -impl std::error::Error - for EVMError +impl std::error::Error + for EVMError where - ChainSpecT: ChainSpec, - ::TransactionValidationError: - std::error::Error + 'static, + DBError: std::error::Error + 'static, + TransactionValidationErrorT: std::error::Error + 'static, { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { @@ -188,7 +191,12 @@ where } } -impl fmt::Display for EVMError { +impl fmt::Display + for EVMError +where + DBError: fmt::Display, + TransactionValidationErrorT: fmt::Display, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Transaction(e) => write!(f, "transaction validation error: {e}"), @@ -199,13 +207,15 @@ impl fmt::Display for EVMError From for EVMError { +impl From for EVMError { fn from(value: InvalidTransaction) -> Self { Self::Transaction(value) } } -impl From for EVMError { +impl From + for EVMError +{ fn from(value: InvalidHeader) -> Self { Self::Header(value) } diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index 225c1e96fc..77533c06ad 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -1,22 +1,7 @@ -use crate::{ - AccessListItem, Address, AuthorizationList, Bytes, InvalidTransaction, TxKind, B256, - GAS_PER_BLOB, U256, -}; -use cfg_if::cfg_if; -use core::fmt::{Debug, Display}; +use crate::{AccessListItem, Address, AuthorizationList, Bytes, TxKind, B256, GAS_PER_BLOB, U256}; /// Trait for retrieving transaction information required for execution. -pub trait Transaction: Clone + Debug + Default + PartialEq + Eq { - cfg_if! { - if #[cfg(feature = "serde")] { - /// The error type that can be returned when validating a transaction. - type TransactionValidationError: Clone + Debug + Display + PartialEq + Eq + serde::de::DeserializeOwned + serde::Serialize + From; - } else { - /// The error type that can be returned when validating a transaction. - type TransactionValidationError: Clone + Debug + Display + PartialEq + Eq + From; - } - } - +pub trait Transaction { /// Caller aka Author aka transaction signer. fn caller(&self) -> &Address; /// The maximum amount of gas the transaction can use. diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index fbe8e3601f..a37d1a1e9b 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -28,6 +28,7 @@ revm-precompile = { path = "../precompile", version = "9.2.0", default-features # misc auto_impl = { version = "1.2", default-features = false } +derive-where = { version = "1.2.7", default-features = false } dyn-clone = "1.0" enumn = { version = "0.1", optional = true } diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index bb5aca9bc0..8274ea06e5 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -4,7 +4,7 @@ use crate::{ register::{self, EvmHandler}, CfgEnvWithChainSpec, EnvWithChainSpec, }, - primitives::{CfgEnv, ChainSpec, Env, EthChainSpec}, + primitives::{CfgEnv, ChainSpec, Env, EthChainSpec, InvalidTransaction, TransactionValidation}, Context, ContextWithChainSpec, Evm, EvmContext, Handler, }; use core::marker::PhantomData; @@ -41,13 +41,19 @@ impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthChainSpec, (), EmptyDB> } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> - EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB> +impl<'a, ChainSpecT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB> +where + ChainSpecT: ChainSpec, { /// Sets the [`ChainSpec`] that will be used by [`Evm`]. - pub fn with_chain_spec( + pub fn with_chain_spec( self, - ) -> EvmBuilder<'a, SetGenericStage, NewChainSpecT, EXT, DB> { + ) -> EvmBuilder<'a, SetGenericStage, NewChainSpecT, EXT, DB> + where + NewChainSpecT: ChainSpec< + Transaction: Default + TransactionValidation>, + >, + { let Context { evm, external } = self.context; EvmBuilder { @@ -58,7 +64,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> phantom: PhantomData, } } +} +impl<'a, ChainSpecT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB> +where + ChainSpecT: + ChainSpec>>, +{ /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, EmptyDB> { EvmBuilder { @@ -167,8 +179,10 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> - EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> +impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> +where + ChainSpecT: + ChainSpec>>, { /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. pub fn reset_handler_with_empty_db( @@ -352,6 +366,18 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> self } + /// Clears Block environment of EVM. + pub fn with_clear_block_env(mut self) -> Self { + self.context.evm.env.block = ChainSpecT::Block::default(); + self + } +} + +impl<'a, BuilderStage, ChainSpecT, EXT, DB> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +where + ChainSpecT: ChainSpec, + DB: Database, +{ /// Clears Environment of EVM. pub fn with_clear_env(mut self) -> Self { self.context.evm.env.clear(); @@ -363,15 +389,13 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> self.context.evm.env.tx = ChainSpecT::Transaction::default(); self } - /// Clears Block environment of EVM. - pub fn with_clear_block_env(mut self) -> Self { - self.context.evm.env.block = ChainSpecT::Block::default(); - self - } } impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +where + ChainSpecT: + ChainSpec>>, { /// Creates the default handler. /// diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index d9685a058a..0217f40d49 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -28,9 +28,12 @@ pub struct Context { pub external: EXT, } -impl Clone for Context +impl Clone for Context where DB::Error: Clone, + ChainSpecT: ChainSpec, + EXT: Clone, + DB: Database + Clone, { fn clone(&self) -> Self { Self { @@ -46,7 +49,10 @@ impl Default for Context { } } -impl Context { +impl Context +where + ChainSpecT: ChainSpec, +{ /// Creates empty context. This is useful for testing. pub fn new_empty() -> Context { Context { @@ -56,7 +62,11 @@ impl Context { } } -impl Context { +impl Context +where + ChainSpecT: ChainSpec, + DB: Database, +{ /// Creates new context with database. pub fn new_with_db(db: DB) -> Context { Context { @@ -88,10 +98,11 @@ impl ContextWithChainSpec Clone - for ContextWithChainSpec +impl Clone for ContextWithChainSpec where - DB::Error: Clone, + ChainSpecT: ChainSpec, + EXT: Clone, + DB: Database + Clone, { fn clone(&self) -> Self { Self { diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index c1e866d093..331da56978 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -3,6 +3,7 @@ use crate::{ precompile::{Precompile, PrecompileResult}, primitives::{db::Database, Address, Bytes, ChainSpec, HashMap, HashSet}, }; +use derive_where::derive_where; use dyn_clone::DynClone; use revm_precompile::{PrecompileSpecId, PrecompileWithAddress, Precompiles}; use std::{boxed::Box, sync::Arc}; @@ -45,18 +46,12 @@ impl Clone for PrecompilesCow { inner: PrecompilesCow, } -impl Clone for ContextPrecompiles { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } -} - impl ContextPrecompiles { /// Creates a new precompiles context at the given spec ID. /// @@ -190,14 +185,6 @@ impl Extend } } -impl Default for ContextPrecompiles { - fn default() -> Self { - Self { - inner: Default::default(), - } - } -} - impl Default for PrecompilesCow { fn default() -> Self { Self::Owned(Default::default()) diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index efaafa5e72..bf23f4e874 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; use revm_interpreter::CallValue; use revm_precompile::PrecompileErrors; @@ -11,17 +12,18 @@ use crate::{ primitives::{ keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, Env, Eof, SpecId::{self, *}, - Transaction as _, B256, EOF_MAGIC_BYTES, + Transaction as _, TransactionValidation, B256, EOF_MAGIC_BYTES, }, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; use core::{ - fmt, + fmt::{self, Debug}, ops::{Deref, DerefMut}, }; use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. +#[derive_where(Clone; ChainSpecT::Transaction, DB, DB::Error)] pub struct EvmContext { /// Inner EVM context. pub inner: InnerEvmContext, @@ -29,24 +31,10 @@ pub struct EvmContext { pub precompiles: ContextPrecompiles, } -impl Clone for EvmContext +impl Debug for EvmContext where - ChainSpecT: ChainSpec, - DB::Error: Clone, -{ - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - precompiles: ContextPrecompiles::default(), - } - } -} - -impl fmt::Debug for EvmContext -where - ChainSpecT: ChainSpec, - DB: Database + fmt::Debug, - DB::Error: fmt::Debug, + ChainSpecT: ChainSpec, + DB: Database + Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("EvmContext") @@ -70,7 +58,11 @@ impl DerefMut for EvmContext EvmContext { +impl EvmContext +where + ChainSpecT: ChainSpec, + DB: Database, +{ /// Create new context with database. pub fn new(db: DB) -> Self { Self { @@ -78,7 +70,9 @@ impl EvmContext { precompiles: ContextPrecompiles::default(), } } +} +impl EvmContext { /// Creates a new context with the given environment and database. #[inline] pub fn new_with_env(db: DB, env: Box>) -> Self { @@ -116,7 +110,13 @@ impl EvmContext { address: &Address, input_data: &Bytes, gas: Gas, - ) -> Result, EVMError> { + ) -> Result< + Option, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { let Some(outcome) = self.precompiles .call(address, input_data, gas.limit(), &mut self.inner) @@ -156,7 +156,13 @@ impl EvmContext { pub fn make_call_frame( &mut self, inputs: &CallInputs, - ) -> Result> { + ) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 1b27cdf673..cad4328db3 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -1,3 +1,5 @@ +use derive_where::derive_where; + use crate::{ db::Database, interpreter::{ @@ -16,7 +18,7 @@ use crate::{ use std::{boxed::Box, sync::Arc, vec::Vec}; /// EVM contexts contains data that EVM needs for execution. -#[derive(Debug)] +#[derive_where(Clone, Debug; ChainSpecT::Transaction, DB, DB::Error)] pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. @@ -31,32 +33,23 @@ pub struct InnerEvmContext { pub valid_authorizations: Vec
, } -impl Clone for InnerEvmContext +impl InnerEvmContext where - DB::Error: Clone, + ChainSpecT: ChainSpec, + DB: Database, { - fn clone(&self) -> Self { - Self { - env: self.env.clone(), - journaled_state: self.journaled_state.clone(), - db: self.db.clone(), - error: self.error.clone(), - valid_authorizations: self.valid_authorizations.clone(), - } - } -} - -impl InnerEvmContext { pub fn new(db: DB) -> Self { Self { env: Box::default(), journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), db, error: Ok(()), - valid_authorizations: Default::default(), + valid_authorizations: Vec::new(), } } +} +impl InnerEvmContext { /// Creates a new context with the given environment and database. #[inline] pub fn new_with_env(db: DB, env: Box>) -> Self { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 7d7e9835fc..759cdec357 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -7,11 +7,11 @@ use crate::{ interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ CfgEnv, ChainSpec, EVMError, EVMResult, EthChainSpec, ExecutionResult, ResultAndState, - SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, + SpecId, Transaction as _, TransactionValidation, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, }; -use core::fmt; +use core::fmt::{self, Debug}; use std::{boxed::Box, vec::Vec}; /// EVM call stack limit. @@ -27,12 +27,11 @@ pub struct Evm<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { pub handler: Handler<'a, ChainSpecT, Context, EXT, DB>, } -impl fmt::Debug for Evm<'_, ChainSpecT, EXT, DB> +impl Debug for Evm<'_, ChainSpecT, EXT, DB> where - ChainSpecT: ChainSpec, - EXT: fmt::Debug, - DB: Database + fmt::Debug, - DB::Error: fmt::Debug, + ChainSpecT: ChainSpec, + EXT: Debug, + DB: Database + Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Evm") @@ -45,7 +44,13 @@ impl Evm<'_, ChainSpe /// Commit the changes to the database. pub fn transact_commit( &mut self, - ) -> Result, EVMError> { + ) -> Result< + ExecutionResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) @@ -83,7 +88,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> pub fn run_the_loop( &mut self, first_frame: Frame, - ) -> Result> { + ) -> Result< + FrameResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { let mut call_stack: Vec = Vec::with_capacity(1025); call_stack.push(first_frame); @@ -188,7 +199,15 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Pre verify transaction by checking Environment, initial gas spend and if caller /// has enough balance to pay for the gas. #[inline] - pub fn preverify_transaction(&mut self) -> Result<(), EVMError> { + pub fn preverify_transaction( + &mut self, + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { let output = self.preverify_transaction_inner().map(|_| ()); self.clear(); output @@ -220,7 +239,15 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Pre verify transaction inner. #[inline] - fn preverify_transaction_inner(&mut self) -> Result> { + fn preverify_transaction_inner( + &mut self, + ) -> Result< + u64, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { self.handler.validation().env(&self.context.evm.env)?; let initial_gas_spend = self .handler diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index d1e9c7f253..6dc457d18f 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -11,7 +11,10 @@ pub use handle_types::*; // Includes. use crate::{ interpreter::{opcode::InstructionTables, Host, InterpreterAction, SharedMemory}, - primitives::{db::Database, spec_to_generic, ChainSpec, EVMError}, + primitives::{ + db::Database, spec_to_generic, ChainSpec, EVMError, InvalidTransaction, + TransactionValidation, + }, Context, Frame, }; use core::mem; @@ -40,7 +43,12 @@ pub struct Handler<'a, ChainSpecT: ChainSpec, H: Host + 'a, EXT, DB: Database> { pub execution: ExecutionHandler<'a, ChainSpecT, EXT, DB>, } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EXT, DB> { +impl<'a, ChainSpecT, EXT, DB> EvmHandler<'a, ChainSpecT, EXT, DB> +where + ChainSpecT: + ChainSpec>>, + DB: Database, +{ /// Creates a base/vanilla Ethereum handler with the provided spec id. pub fn mainnet_with_spec(spec_id: ChainSpecT::Hardfork) -> Self { spec_to_generic!( @@ -56,7 +64,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EX } ) } +} +impl<'a, ChainSpecT, EXT, DB> EvmHandler<'a, ChainSpecT, EXT, DB> +where + ChainSpecT: ChainSpec, + DB: Database, +{ /// Returns the specification ID. pub fn spec_id(&self) -> ChainSpecT::Hardfork { self.spec_id @@ -68,7 +82,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EX frame: &mut Frame, shared_memory: &mut SharedMemory, context: &mut Context, - ) -> Result> { + ) -> Result< + InterpreterAction, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { self.execution .execute_frame(frame, shared_memory, &self.instruction_table, context) } @@ -134,7 +154,12 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EX } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmHandler<'a, ChainSpecT, EXT, DB> { +impl<'a, ChainSpecT, EXT, DB> EvmHandler<'a, ChainSpecT, EXT, DB> +where + ChainSpecT: + ChainSpec>>, + DB: Database, +{ /// Pop last handle register and reapply all registers that are left. pub fn pop_handle_register(&mut self) -> Option> { let out = self.registers.pop(); diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs index cf613ac4f7..2763623fc2 100644 --- a/crates/revm/src/handler/cfg.rs +++ b/crates/revm/src/handler/cfg.rs @@ -1,6 +1,11 @@ -use core::ops::{Deref, DerefMut}; +use core::{ + fmt::Debug, + ops::{Deref, DerefMut}, +}; use std::boxed::Box; +use derive_where::derive_where; + use crate::primitives::{CfgEnv, ChainSpec, Env}; /// Configuration environment with the chain spec id. @@ -34,15 +39,21 @@ impl Deref for CfgEnvWithChainSpec { } /// Evm environment with the chain spec id. -#[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct EnvWithChainSpec { +#[derive_where(Clone, Debug; ChainSpecT::Hardfork, ChainSpecT::Transaction)] +pub struct EnvWithChainSpec +where + ChainSpecT: ChainSpec, +{ /// Evm enironment. pub env: Box>, /// Handler configuration fields. pub spec_id: ChainSpecT::Hardfork, } -impl EnvWithChainSpec { +impl EnvWithChainSpec +where + ChainSpecT: ChainSpec, +{ /// Returns new `EnvWithHandlerCfg` instance. pub fn new(env: Box>, spec_id: ChainSpecT::Hardfork) -> Self { Self { env, spec_id } @@ -63,13 +74,19 @@ impl EnvWithChainSpec { } } -impl DerefMut for EnvWithChainSpec { +impl DerefMut for EnvWithChainSpec +where + ChainSpecT: ChainSpec, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.env } } -impl Deref for EnvWithChainSpec { +impl Deref for EnvWithChainSpec +where + ChainSpecT: ChainSpec, +{ type Target = Env; fn deref(&self) -> &Self::Target { diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index 238b2a8542..3cdc7d1369 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -2,7 +2,7 @@ use crate::{ frame::EOFCreateFrame, handler::mainnet, interpreter::{CallInputs, CreateInputs, SharedMemory}, - primitives::{db::Database, ChainSpec, EVMError, Spec}, + primitives::{db::Database, ChainSpec, EVMError, Spec, TransactionValidation}, CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ @@ -16,8 +16,13 @@ pub type LastFrameReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, &mut FrameResult, - ) -> Result<(), EVMError::Error>> - + 'a, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Executes a single frame. Errors can be returned in the EVM context. @@ -27,8 +32,13 @@ pub type ExecuteFrameHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut SharedMemory, &InstructionTables<'_, Context>, &mut Context, - ) -> Result::Error>> - + 'a, + ) -> Result< + InterpreterAction, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handle sub call. @@ -36,8 +46,13 @@ pub type FrameCallHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, Box, - ) -> Result::Error>> - + 'a, + ) -> Result< + FrameOrResult, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handle call return @@ -46,8 +61,13 @@ pub type FrameCallReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result::Error>> - + 'a, + ) -> Result< + CallOutcome, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Insert call outcome to the parent @@ -57,8 +77,13 @@ pub type InsertCallOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Frame, &mut SharedMemory, CallOutcome, - ) -> Result<(), EVMError::Error>> - + 'a, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handle sub create. @@ -66,8 +91,13 @@ pub type FrameCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, Box, - ) -> Result::Error>> - + 'a, + ) -> Result< + FrameOrResult, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handle create return @@ -76,8 +106,13 @@ pub type FrameCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result::Error>> - + 'a, + ) -> Result< + CreateOutcome, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Insert call outcome to the parent @@ -86,8 +121,13 @@ pub type InsertCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, &mut Frame, CreateOutcome, - ) -> Result<(), EVMError::Error>> - + 'a, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handle EOF sub create. @@ -95,8 +135,13 @@ pub type FrameEOFCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, Box, - ) -> Result::Error>> - + 'a, + ) -> Result< + FrameOrResult, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handle EOF create return @@ -105,8 +150,13 @@ pub type FrameEOFCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result::Error>> - + 'a, + ) -> Result< + CreateOutcome, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Insert EOF crate outcome to the parent @@ -115,8 +165,13 @@ pub type InsertEOFCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, &mut Frame, CreateOutcome, - ) -> Result<(), EVMError::Error>> - + 'a, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handles related to stack frames. @@ -176,7 +231,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe shared_memory: &mut SharedMemory, instruction_tables: &InstructionTables<'_, Context>, context: &mut Context, - ) -> Result> { + ) -> Result< + InterpreterAction, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.execute_frame)(frame, shared_memory, instruction_tables, context) } @@ -186,7 +247,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, frame_result: &mut FrameResult, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.last_frame_return)(context, frame_result) } @@ -196,7 +263,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, inputs: Box, - ) -> Result> { + ) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.call)(context, inputs) } @@ -207,7 +280,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result< + CallOutcome, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.call_return)(context, frame, interpreter_result) } @@ -219,7 +298,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.insert_call_outcome)(context, frame, shared_memory, outcome) } @@ -229,7 +314,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, inputs: Box, - ) -> Result> { + ) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.create)(context, inputs) } @@ -240,7 +331,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result< + CreateOutcome, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.create_return)(context, frame, interpreter_result) } @@ -251,7 +348,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.insert_create_outcome)(context, frame, outcome) } @@ -261,7 +364,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, inputs: Box, - ) -> Result> { + ) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.eofcreate)(context, inputs) } @@ -272,7 +381,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result< + CreateOutcome, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.eofcreate_return)(context, frame, interpreter_result) } @@ -283,7 +398,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.insert_eofcreate_outcome)(context, frame, outcome) } } diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index dcf5cb72ca..fc26c7eeda 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -2,7 +2,10 @@ use crate::{ handler::mainnet, interpreter::Gas, - primitives::{db::Database, ChainSpec, EVMError, EVMResultGeneric, ResultAndState, Spec}, + primitives::{ + db::Database, ChainSpec, EVMError, EVMResultGeneric, ResultAndState, Spec, + TransactionValidation, + }, Context, FrameResult, }; use std::sync::Arc; @@ -25,9 +28,13 @@ pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, FrameResult, - ) - -> Result, EVMError::Error>> - + 'a, + ) -> Result< + ResultAndState, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// End handle, takes result and state and returns final result. @@ -37,9 +44,9 @@ pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< pub type EndHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, - Result, EVMError::Error>>, + Result, EVMError<::Error, <::Transaction as TransactionValidation>::ValidationError>>, ) - -> Result, EVMError::Error>> + -> Result, EVMError<::Error, <::Transaction as TransactionValidation>::ValidationError>> + 'a, >; @@ -85,7 +92,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, gas: &Gas, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.reimburse_caller)(context, gas) } /// Reward beneficiary @@ -93,7 +106,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, gas: &Gas, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.reward_beneficiary)(context, gas) } @@ -102,7 +121,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, result: FrameResult, - ) -> Result, EVMError> { + ) -> Result< + ResultAndState, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.output)(context, result) } @@ -110,8 +135,20 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai pub fn end( &self, context: &mut Context, - end_output: Result, EVMError>, - ) -> Result, EVMError> { + end_output: Result< + ResultAndState, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + >, + ) -> Result< + ResultAndState, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.end)(context, end_output) } diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index baaf3dd677..2f54ddd80f 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -1,7 +1,9 @@ // Includes. use crate::{ handler::mainnet, - primitives::{db::Database, ChainSpec, EVMError, EVMResultGeneric, Spec}, + primitives::{ + db::Database, ChainSpec, EVMError, EVMResultGeneric, Spec, TransactionValidation, + }, Context, ContextPrecompiles, }; use std::sync::Arc; @@ -16,8 +18,13 @@ pub type LoadPrecompilesHandle<'a, ChainSpecT, DB> = pub type LoadAccountsHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, - ) -> Result<(), EVMError::Error>> - + 'a, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Deduct the caller to its limit. @@ -56,7 +63,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PreExecutionHandler<'a, Chain pub fn deduct_caller( &self, context: &mut Context, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.deduct_caller)(context) } @@ -64,7 +77,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PreExecutionHandler<'a, Chain pub fn load_accounts( &self, context: &mut Context, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.load_accounts)(context) } diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index 1cc8b2abbb..c12e711804 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -1,26 +1,50 @@ use crate::{ handler::mainnet, - primitives::{db::Database, ChainSpec, EVMError, Env, Spec}, + primitives::{ + db::Database, ChainSpec, EVMError, Env, InvalidTransaction, Spec, TransactionValidation, + }, Context, }; use std::sync::Arc; /// Handle that validates env. -pub type ValidateEnvHandle<'a, ChainSpecT, DB> = - Arc) -> Result<(), EVMError::Error>> + 'a>; +pub type ValidateEnvHandle<'a, ChainSpecT, DB> = Arc< + dyn Fn( + &Env, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, +>; /// Handle that validates transaction environment against the state. /// Second parametar is initial gas. pub type ValidateTxEnvAgainstState<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, - ) -> Result<(), EVMError::Error>> - + 'a, + ) -> Result< + (), + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Initial gas calculation handle pub type ValidateInitialTxGasHandle<'a, ChainSpecT, DB> = Arc< - dyn Fn(&Env) -> Result::Error>> + 'a, + dyn Fn( + &Env, + ) -> Result< + u64, + EVMError< + ::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > + 'a, >; /// Handles related to validation. @@ -35,6 +59,8 @@ pub struct ValidationHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> ValidationHandler<'a, ChainSpecT, EXT, DB> +where + ::ValidationError: From, { /// Create new ValidationHandles pub fn new() -> Self { @@ -50,7 +76,16 @@ impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSpecT, EXT, DB> { /// Validate env. - pub fn env(&self, env: &Env) -> Result<(), EVMError> { + pub fn env( + &self, + env: &Env, + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.env)(env) } @@ -58,7 +93,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSp pub fn initial_tx_gas( &self, env: &Env, - ) -> Result> { + ) -> Result< + u64, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.initial_tx_gas)(env) } @@ -66,7 +107,13 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSp pub fn tx_against_state( &self, context: &mut Context, - ) -> Result<(), EVMError> { + ) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { (self.tx_against_state)(context) } } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 08208fe733..f98d24f510 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -5,7 +5,7 @@ use crate::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, SharedMemory, }, - primitives::{ChainSpec, EVMError, Env, Spec, SpecId, Transaction}, + primitives::{ChainSpec, EVMError, Env, Spec, SpecId, Transaction, TransactionValidation}, CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use core::mem; @@ -22,7 +22,13 @@ pub fn execute_frame( shared_memory: &mut SharedMemory, instruction_tables: &InstructionTables<'_, Context>, context: &mut Context, -) -> Result> { +) -> Result< + InterpreterAction, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { let interpreter = frame.interpreter_mut(); let memory = mem::replace(shared_memory, EMPTY_SHARED_MEMORY); let next_action = match instruction_tables { @@ -76,7 +82,13 @@ pub fn frame_return_with_refund_flag( pub fn last_frame_return( context: &mut Context, frame_result: &mut FrameResult, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { frame_return_with_refund_flag::(&context.evm.env, frame_result, true); Ok(()) } @@ -86,7 +98,13 @@ pub fn last_frame_return( pub fn call( context: &mut Context, inputs: Box, -) -> Result> { +) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context.evm.make_call_frame(&inputs) } @@ -95,7 +113,13 @@ pub fn call_return( context: &mut Context, frame: Box, interpreter_result: InterpreterResult, -) -> Result> { +) -> Result< + CallOutcome, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context .evm .call_return(&interpreter_result, frame.frame_data.checkpoint); @@ -111,7 +135,13 @@ pub fn insert_call_outcome( frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -126,7 +156,13 @@ pub fn insert_call_outcome( pub fn create( context: &mut Context, inputs: Box, -) -> Result> { +) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context .evm .make_create_frame(SPEC::SPEC_ID, &inputs) @@ -138,7 +174,13 @@ pub fn create_return( context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result> { +) -> Result< + CreateOutcome, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context.evm.create_return::( &mut interpreter_result, frame.created_address, @@ -155,7 +197,13 @@ pub fn insert_create_outcome( context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -170,7 +218,13 @@ pub fn insert_create_outcome( pub fn eofcreate( context: &mut Context, inputs: Box, -) -> Result> { +) -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context .evm .make_eofcreate_frame(SPEC::SPEC_ID, &inputs) @@ -182,7 +236,13 @@ pub fn eofcreate_return( context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result> { +) -> Result< + CreateOutcome, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context.evm.eofcreate_return::( &mut interpreter_result, frame.created_address, @@ -199,7 +259,13 @@ pub fn insert_eofcreate_outcome( context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { core::mem::replace(&mut context.evm.error, Ok(())).map_err(EVMError::Database)?; frame diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index e1df54b80c..5dbe875281 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -2,7 +2,7 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ db::Database, Block, Bytecode, ChainSpec, EVMError, ExecutionResult, ResultAndState, Spec, - SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, + SpecId::LONDON, Transaction, TransactionValidation, KECCAK_EMPTY, U256, }, Context, FrameResult, }; @@ -11,8 +11,20 @@ use crate::{ #[inline] pub fn end( _context: &mut Context, - evm_output: Result, EVMError>, -) -> Result, EVMError> { + evm_output: Result< + ResultAndState, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + >, +) -> Result< + ResultAndState, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { evm_output } @@ -32,7 +44,13 @@ pub fn clear(context: &mut Context( context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { let beneficiary = *context.evm.env.block.coinbase(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -64,7 +82,13 @@ pub fn reward_beneficiary( pub fn reimburse_caller( context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { let caller = context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -89,7 +113,13 @@ pub fn reimburse_caller( pub fn output( context: &mut Context, result: FrameResult, -) -> Result, EVMError> { +) -> Result< + ResultAndState, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { context.evm.take_error().map_err(EVMError::Database)?; // used gas with refund calculated. diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 9675b34f93..8858434adc 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -6,7 +6,7 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ db::Database, Account, Block, ChainSpec, EVMError, Env, Spec, SpecId, Transaction as _, - BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, + TransactionValidation, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, }; @@ -23,7 +23,13 @@ pub fn load_precompiles( #[inline] pub fn load_accounts( context: &mut Context, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { // set journaling state flag. context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); @@ -156,7 +162,13 @@ pub fn deduct_caller_inner( #[inline] pub fn deduct_caller( context: &mut Context, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> { // load caller's account. let (caller_account, _) = context .evm diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index c337bb0bf3..3946a4b7b0 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -1,14 +1,26 @@ use revm_interpreter::gas; use crate::{ - primitives::{db::Database, ChainSpec, EVMError, Env, InvalidTransaction, Spec, Transaction}, + primitives::{ + db::Database, ChainSpec, EVMError, Env, InvalidTransaction, Spec, Transaction, + TransactionValidation, + }, Context, }; /// Validate environment for the mainnet. pub fn validate_env( env: &Env, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> +where + ::ValidationError: From, +{ // Important: validate block before tx. env.validate_block_env::()?; env.validate_tx::() @@ -19,7 +31,16 @@ pub fn validate_env( /// Validates transaction against the state. pub fn validate_tx_against_state( context: &mut Context, -) -> Result<(), EVMError> { +) -> Result< + (), + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> +where + ::ValidationError: From, +{ // load acc let tx_caller = context.evm.env.tx.caller(); let (caller_account, _) = context @@ -42,7 +63,16 @@ pub fn validate_tx_against_state( env: &Env, -) -> Result> { +) -> Result< + u64, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, +> +where + ::ValidationError: From, +{ let input = &env.tx.data(); let is_create = env.tx.kind().is_create(); let access_list = &env.tx.access_list(); diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index f1d2e5c312..6e34d72cb3 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -2,7 +2,7 @@ use crate::{ db::Database, handler::register::EvmHandler, interpreter::{opcode, InstructionResult, Interpreter}, - primitives::{ChainSpec, EVMError}, + primitives::{ChainSpec, EVMError, TransactionValidation}, Context, FrameOrResult, FrameResult, Inspector, JournalEntry, }; use core::cell::RefCell; @@ -96,7 +96,15 @@ pub fn inspector_handle_register< let create_input_stack_inner = create_input_stack.clone(); let prev_handle = handler.execution.create.clone(); handler.execution.create = Arc::new( - move |ctx, mut inputs| -> Result> { + move |ctx, + mut inputs| + -> Result< + FrameOrResult, + EVMError< + DB::Error, + <::Transaction as TransactionValidation>::ValidationError, + >, + > { let inspector = ctx.external.get_inspector(); // call inspector create to change input or return outcome. if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index 372e5547db..5d6e9ea75c 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -1,7 +1,7 @@ use crate::{ primitives::{ db::Database, AccessListItem, Address, AuthorizationList, BlobExcessGasAndPrice, Block, - BlockEnv, Bytes, TransactTo, Transaction, TxEnv, B256, U256, + BlockEnv, Bytes, Transaction, TransactionValidation, TxEnv, TxKind, B256, U256, }, L1BlockInfo, }; @@ -115,8 +115,6 @@ pub struct OptimismTransaction { } impl Transaction for OptimismTransaction { - type TransactionValidationError = OptimismInvalidTransaction; - fn caller(&self) -> &Address { self.base.caller() } @@ -129,7 +127,7 @@ impl Transaction for OptimismTransaction { self.base.gas_price() } - fn kind(&self) -> &TransactTo { + fn kind(&self) -> &TxKind { self.base.kind() } @@ -169,3 +167,7 @@ impl Transaction for OptimismTransaction { self.base.authorization_list() } } + +impl TransactionValidation for OptimismTransaction { + type ValidationError = OptimismInvalidTransaction; +} diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 576da94fd7..bd67baf5e9 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -49,7 +49,7 @@ pub fn optimism_handle_register( /// Validate environment for the Optimism chain. pub fn validate_env( env: &Env, -) -> Result<(), EVMError> { +) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. if env.tx.source_hash.is_some() { if env.block.l1_block_info().is_some() { @@ -81,7 +81,7 @@ pub fn validate_env( /// Don not perform any extra validation for deposit transactions, they are pre-verified on L1. pub fn validate_tx_against_state( context: &mut Context, -) -> Result<(), EVMError> { +) -> Result<(), EVMError> { if context.evm.inner.env.tx.source_hash.is_some() { return Ok(()); } @@ -93,7 +93,7 @@ pub fn validate_tx_against_state( pub fn last_frame_return( context: &mut Context, frame_result: &mut FrameResult, -) -> Result<(), EVMError> { +) -> Result<(), EVMError> { let env = context.evm.inner.env(); let is_deposit = env.tx.source_hash.is_some(); let tx_system = env.tx.is_system_transaction; @@ -180,7 +180,7 @@ pub fn load_precompiles( #[inline] pub fn deduct_caller( context: &mut Context, -) -> Result<(), EVMError> { +) -> Result<(), EVMError> { // load caller's account. let (caller_account, _) = context .evm @@ -240,7 +240,7 @@ pub fn deduct_caller( pub fn reward_beneficiary( context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { +) -> Result<(), EVMError> { let is_deposit = context.evm.inner.env.tx.source_hash.is_some(); // transfer fee to coinbase/beneficiary. @@ -301,7 +301,7 @@ pub fn reward_beneficiary( pub fn output( context: &mut Context, frame_result: FrameResult, -) -> Result, EVMError> { +) -> Result, EVMError> { let result = mainnet::output::(context, frame_result)?; if result.result.is_halt() { @@ -322,8 +322,11 @@ pub fn output( #[inline] pub fn end( context: &mut Context, - evm_output: Result, EVMError>, -) -> Result, EVMError> { + evm_output: Result< + ResultAndState, + EVMError, + >, +) -> Result, EVMError> { evm_output.or_else(|err| { if matches!(err, EVMError::Transaction(_)) && context.evm.inner.env().tx.source_hash.is_some() diff --git a/crates/revm/src/optimism/result.rs b/crates/revm/src/optimism/result.rs index 2fc4a8748c..75bd6b8165 100644 --- a/crates/revm/src/optimism/result.rs +++ b/crates/revm/src/optimism/result.rs @@ -2,8 +2,6 @@ use core::fmt::Display; use crate::primitives::{EVMError, HaltReason, InvalidTransaction}; -use super::OptimismChainSpec; - /// Optimism transaction validation error. #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -80,7 +78,7 @@ impl From for OptimismInvalidTransaction { } } -impl From for EVMError { +impl From for EVMError { fn from(value: OptimismInvalidTransaction) -> Self { Self::Transaction(value) } From caaf05d48afabc4857b15a2e09808230bb765e9c Mon Sep 17 00:00:00 2001 From: Wodann Date: Tue, 18 Jun 2024 20:59:22 +0000 Subject: [PATCH 04/59] refactor: remove trait bounds from Block supertrait --- crates/interpreter/src/host/dummy.rs | 41 ++++++++++++++++--- crates/primitives/src/chain_spec.rs | 3 +- crates/primitives/src/env.rs | 4 +- crates/revm/src/builder.rs | 25 ++++++++--- crates/revm/src/context.rs | 8 ++-- .../revm/src/context/context_precompiles.rs | 24 ++++------- crates/revm/src/context/evm_context.rs | 22 ++-------- crates/revm/src/context/inner_evm_context.rs | 4 +- crates/revm/src/evm.rs | 8 ++-- crates/revm/src/handler/cfg.rs | 2 +- 10 files changed, 79 insertions(+), 62 deletions(-) diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index d7772c621f..b4083308eb 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -10,10 +10,9 @@ use std::vec::Vec; use super::LoadAccountResult; /// A dummy [Host] implementation. -#[derive(Clone, Debug)] pub struct DummyHost where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, { pub env: Env, pub storage: HashMap, @@ -23,14 +22,16 @@ where impl DummyHost where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, { /// Create a new dummy host with the given [`Env`]. #[inline] pub fn new(env: Env) -> Self { Self { env, - ..DummyHost::default() + storage: HashMap::new(), + transient_storage: HashMap::new(), + log: Vec::new(), } } @@ -42,9 +43,37 @@ where } } +impl Clone for DummyHost +where + ChainSpecT: ChainSpec, +{ + fn clone(&self) -> Self { + Self { + env: self.env.clone(), + storage: self.storage.clone(), + transient_storage: self.transient_storage.clone(), + log: self.log.clone(), + } + } +} + +impl Debug for DummyHost +where + ChainSpecT: ChainSpec, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("DummyHost") + .field("env", &self.env) + .field("storage", &self.storage) + .field("transient_storage", &self.transient_storage) + .field("log", &self.log) + .finish() + } +} + impl Default for DummyHost where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, { fn default() -> Self { Self { @@ -58,7 +87,7 @@ where impl Host for DummyHost where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, { type ChainSpecT = ChainSpecT; diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 52566c5983..70b29728cb 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -46,11 +46,10 @@ pub trait TransactionValidation { pub trait ChainSpec: Sized + 'static { /// The type that contains all block information. - type Block: Block + Clone + Debug + Default + PartialEq + Eq; + type Block: Block; /// The type that contains all transaction information. type Transaction: Transaction + TransactionValidation; - // Clone + Debug + Default + PartialEq + Eq /// The type that enumerates the chain's hardforks. type Hardfork: HardforkTrait; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 03b2fc6953..78550067ee 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -19,7 +19,7 @@ use std::boxed::Box; use std::vec::Vec; /// EVM environment configuration. -#[derive_where(Clone, Debug, Default; ChainSpecT::Transaction)] +#[derive_where(Clone, Debug, Default; ChainSpecT::Block, ChainSpecT::Transaction)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Env { /// Configuration of the EVM itself. @@ -266,7 +266,7 @@ impl Env { } } -impl> Env { +impl> Env { /// Resets environment to default values. #[inline] pub fn clear(&mut self) { diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 8274ea06e5..fe48720df1 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -51,6 +51,7 @@ where ) -> EvmBuilder<'a, SetGenericStage, NewChainSpecT, EXT, DB> where NewChainSpecT: ChainSpec< + Block: Default, Transaction: Default + TransactionValidation>, >, { @@ -365,7 +366,13 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> f(&mut self.context.evm.env.cfg); self } +} +impl<'a, BuilderStage, ChainSpecT, EXT, DB> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +where + ChainSpecT: ChainSpec, + DB: Database, +{ /// Clears Block environment of EVM. pub fn with_clear_block_env(mut self) -> Self { self.context.evm.env.block = ChainSpecT::Block::default(); @@ -378,12 +385,6 @@ where ChainSpecT: ChainSpec, DB: Database, { - /// Clears Environment of EVM. - pub fn with_clear_env(mut self) -> Self { - self.context.evm.env.clear(); - self - } - /// Clears Transaction environment of EVM. pub fn with_clear_tx_env(mut self) -> Self { self.context.evm.env.tx = ChainSpecT::Transaction::default(); @@ -391,6 +392,18 @@ where } } +impl<'a, BuilderStage, ChainSpecT, EXT, DB> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +where + ChainSpecT: ChainSpec, + DB: Database, +{ + /// Clears Environment of EVM. + pub fn with_clear_env(mut self) -> Self { + self.context.evm.env.clear(); + self + } +} + impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> where diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 0217f40d49..fecb35a960 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -31,7 +31,7 @@ pub struct Context { impl Clone for Context where DB::Error: Clone, - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, EXT: Clone, DB: Database + Clone, { @@ -51,7 +51,7 @@ impl Default for Context { impl Context where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, { /// Creates empty context. This is useful for testing. pub fn new_empty() -> Context { @@ -64,7 +64,7 @@ where impl Context where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, DB: Database, { /// Creates new context with database. @@ -100,7 +100,7 @@ impl ContextWithChainSpec Clone for ContextWithChainSpec where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, EXT: Clone, DB: Database + Clone, { diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index 331da56978..6e68ca6744 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -3,12 +3,14 @@ use crate::{ precompile::{Precompile, PrecompileResult}, primitives::{db::Database, Address, Bytes, ChainSpec, HashMap, HashSet}, }; +use core::fmt::Debug; use derive_where::derive_where; use dyn_clone::DynClone; use revm_precompile::{PrecompileSpecId, PrecompileWithAddress, Precompiles}; use std::{boxed::Box, sync::Arc}; /// A single precompile handler. +#[derive_where(Clone)] pub enum ContextPrecompile { /// Ordinary precompiles Ordinary(Precompile), @@ -20,34 +22,26 @@ pub enum ContextPrecompile { ContextStatefulMut(ContextStatefulPrecompileBox), } -impl Clone for ContextPrecompile { - fn clone(&self) -> Self { +impl Debug for ContextPrecompile { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::Ordinary(p) => Self::Ordinary(p.clone()), - Self::ContextStateful(p) => Self::ContextStateful(p.clone()), - Self::ContextStatefulMut(p) => Self::ContextStatefulMut(p.clone()), + Self::Ordinary(arg0) => f.debug_tuple("Ordinary").field(arg0).finish(), + Self::ContextStateful(_arg0) => f.debug_tuple("ContextStateful").finish(), + Self::ContextStatefulMut(_arg0) => f.debug_tuple("ContextStatefulMut").finish(), } } } +#[derive_where(Clone, Debug)] enum PrecompilesCow { /// Default precompiles, returned by `Precompiles::new`. Used to fast-path the default case. StaticRef(&'static Precompiles), Owned(HashMap>), } -impl Clone for PrecompilesCow { - fn clone(&self) -> Self { - match *self { - PrecompilesCow::StaticRef(p) => PrecompilesCow::StaticRef(p), - PrecompilesCow::Owned(ref inner) => PrecompilesCow::Owned(inner.clone()), - } - } -} - /// Precompiles context. -#[derive_where(Clone, Default)] +#[derive_where(Clone, Debug, Default)] pub struct ContextPrecompiles { inner: PrecompilesCow, } diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index bf23f4e874..eeeec6894e 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -16,14 +16,11 @@ use crate::{ }, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; -use core::{ - fmt::{self, Debug}, - ops::{Deref, DerefMut}, -}; +use core::ops::{Deref, DerefMut}; use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. -#[derive_where(Clone; ChainSpecT::Transaction, DB, DB::Error)] +#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Transaction, DB, DB::Error)] pub struct EvmContext { /// Inner EVM context. pub inner: InnerEvmContext, @@ -31,19 +28,6 @@ pub struct EvmContext { pub precompiles: ContextPrecompiles, } -impl Debug for EvmContext -where - ChainSpecT: ChainSpec, - DB: Database + Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("EvmContext") - .field("inner", &self.inner) - .field("precompiles", &self.inner) - .finish_non_exhaustive() - } -} - impl Deref for EvmContext { type Target = InnerEvmContext; @@ -60,7 +44,7 @@ impl DerefMut for EvmContext EvmContext where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, DB: Database, { /// Create new context with database. diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index cad4328db3..8d502abfc3 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -18,7 +18,7 @@ use crate::{ use std::{boxed::Box, sync::Arc, vec::Vec}; /// EVM contexts contains data that EVM needs for execution. -#[derive_where(Clone, Debug; ChainSpecT::Transaction, DB, DB::Error)] +#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Transaction, DB, DB::Error)] pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. @@ -35,7 +35,7 @@ pub struct InnerEvmContext { impl InnerEvmContext where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, DB: Database, { pub fn new(db: DB) -> Self { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 759cdec357..509930cb97 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -29,7 +29,7 @@ pub struct Evm<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { impl Debug for Evm<'_, ChainSpecT, EXT, DB> where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, EXT: Debug, DB: Database + Debug, { @@ -42,14 +42,12 @@ where impl Evm<'_, ChainSpecT, EXT, DB> { /// Commit the changes to the database. + #[allow(clippy::type_complexity)] pub fn transact_commit( &mut self, ) -> Result< ExecutionResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, + EVMError::ValidationError>, > { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs index 2763623fc2..7847c9731b 100644 --- a/crates/revm/src/handler/cfg.rs +++ b/crates/revm/src/handler/cfg.rs @@ -39,7 +39,7 @@ impl Deref for CfgEnvWithChainSpec { } /// Evm environment with the chain spec id. -#[derive_where(Clone, Debug; ChainSpecT::Hardfork, ChainSpecT::Transaction)] +#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Hardfork, ChainSpecT::Transaction)] pub struct EnvWithChainSpec where ChainSpecT: ChainSpec, From 72272c9baffd6202cafe928540f4211284016a8f Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 14:16:02 +0000 Subject: [PATCH 05/59] fix: clippy warnings --- crates/primitives/src/result.rs | 9 ++++- crates/revm/src/context/evm_context.rs | 11 ++---- crates/revm/src/evm.rs | 10 ++--- .../handler/handle_types/post_execution.rs | 28 +++----------- .../src/handler/mainnet/post_execution.rs | 37 ++++--------------- 5 files changed, 25 insertions(+), 70 deletions(-) diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 01dce7a6dc..852266b5d7 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -158,9 +158,9 @@ pub enum EVMError { Precompile(String), } -impl EVMError { +impl EVMError { /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged. - pub fn map_db_err(self, op: F) -> EVMError + pub fn map_db_err(self, op: F) -> EVMError where F: FnOnce(DBError) -> E, { @@ -174,6 +174,11 @@ impl EVMError { } } +pub type EVMErrorForChain = EVMError< + DBError, + <::Transaction as TransactionValidation>::ValidationError, +>; + #[cfg(feature = "std")] impl std::error::Error for EVMError diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index eeeec6894e..9eccab976b 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -10,7 +10,8 @@ use crate::{ EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, primitives::{ - keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, Env, Eof, + keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, EVMErrorForChain, + Env, Eof, SpecId::{self, *}, Transaction as _, TransactionValidation, B256, EOF_MAGIC_BYTES, }, @@ -94,13 +95,7 @@ impl EvmContext { address: &Address, input_data: &Bytes, gas: Gas, - ) -> Result< - Option, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> Result, EVMErrorForChain> { let Some(outcome) = self.precompiles .call(address, input_data, gas.limit(), &mut self.inner) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 509930cb97..6cce8118ff 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,8 +6,8 @@ use crate::{ handler::{EnvWithChainSpec, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, ChainSpec, EVMError, EVMResult, EthChainSpec, ExecutionResult, ResultAndState, - SpecId, Transaction as _, TransactionValidation, TxKind, EOF_MAGIC_BYTES, + CfgEnv, ChainSpec, EVMError, EVMErrorForChain, EVMResult, EthChainSpec, ExecutionResult, + ResultAndState, SpecId, Transaction as _, TransactionValidation, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, }; @@ -42,13 +42,9 @@ where impl Evm<'_, ChainSpecT, EXT, DB> { /// Commit the changes to the database. - #[allow(clippy::type_complexity)] pub fn transact_commit( &mut self, - ) -> Result< - ExecutionResult, - EVMError::ValidationError>, - > { + ) -> Result, EVMErrorForChain> { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index fc26c7eeda..476cad73d7 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -3,8 +3,8 @@ use crate::{ handler::mainnet, interpreter::Gas, primitives::{ - db::Database, ChainSpec, EVMError, EVMResultGeneric, ResultAndState, Spec, - TransactionValidation, + db::Database, ChainSpec, EVMError, EVMErrorForChain, EVMResultGeneric, ResultAndState, + Spec, TransactionValidation, }, Context, FrameResult, }; @@ -121,13 +121,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, result: FrameResult, - ) -> Result< - ResultAndState, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> Result, EVMErrorForChain> { (self.output)(context, result) } @@ -135,20 +129,8 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai pub fn end( &self, context: &mut Context, - end_output: Result< - ResultAndState, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - >, - ) -> Result< - ResultAndState, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + end_output: Result, EVMErrorForChain>, + ) -> Result, EVMErrorForChain> { (self.end)(context, end_output) } diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index 5dbe875281..fe50fad9b8 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,8 +1,9 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, Block, Bytecode, ChainSpec, EVMError, ExecutionResult, ResultAndState, Spec, - SpecId::LONDON, Transaction, TransactionValidation, KECCAK_EMPTY, U256, + db::Database, Block, Bytecode, ChainSpec, EVMError, EVMErrorForChain, ExecutionResult, + ResultAndState, Spec, SpecId::LONDON, Transaction, TransactionValidation, KECCAK_EMPTY, + U256, }, Context, FrameResult, }; @@ -11,20 +12,8 @@ use crate::{ #[inline] pub fn end( _context: &mut Context, - evm_output: Result< - ResultAndState, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - >, -) -> Result< - ResultAndState, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { + evm_output: Result, EVMErrorForChain>, +) -> Result, EVMErrorForChain> { evm_output } @@ -82,13 +71,7 @@ pub fn reward_beneficiary( pub fn reimburse_caller( context: &mut Context, gas: &Gas, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> Result<(), EVMErrorForChain> { let caller = context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -113,13 +96,7 @@ pub fn reimburse_caller( pub fn output( context: &mut Context, result: FrameResult, -) -> Result< - ResultAndState, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> Result, EVMErrorForChain> { context.evm.take_error().map_err(EVMError::Database)?; // used gas with refund calculated. From 0723ff0e091d332daf256f48fc7c6c6e72a135e6 Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 14:17:47 +0000 Subject: [PATCH 06/59] fix: cargo doc --- crates/primitives/src/transaction.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index 77533c06ad..ac9d163fb1 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -16,7 +16,9 @@ pub trait Transaction { fn data(&self) -> &Bytes; /// The nonce of the transaction. /// - /// Caution: If set to `None`, then nonce validation against the account's nonce is skipped: [InvalidTransaction::NonceTooHigh] and [InvalidTransaction::NonceTooLow] + /// Caution: If set to `None`, then nonce validation against the account's + /// nonce is skipped: [`crate::InvalidTransaction::NonceTooHigh`] and + /// [`crate::InvalidTransaction::NonceTooLow`] fn nonce(&self) -> Option; /// The chain ID of the transaction. If set to `None`, no checks are performed. /// From f5ccf5412b9011cfdaea41dced3f69e6bfc3f01b Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 14:29:36 +0000 Subject: [PATCH 07/59] refactor: limit trait bounds on HaltReason --- crates/primitives/src/chain_spec.rs | 22 +++++----------------- crates/primitives/src/result.rs | 2 -- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 70b29728cb..4b383fb944 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -12,24 +12,12 @@ impl HardforkTrait for HardforkT where { } -cfg_if! { - if #[cfg(feature = "serde")] { - /// The type that enumerates chain-specific halt reasons. - pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + Hash + From + serde::de::DeserializeOwned + serde::Serialize {} +/// The type that enumerates chain-specific halt reasons. +pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From {} - impl HaltReasonTrait for HaltReasonT where - HaltReasonT: Clone + Debug + PartialEq + Eq + Hash + From + serde::de::DeserializeOwned + serde::Serialize - { - } - } else { - /// The type that enumerates chain-specific halt reasons. - pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + Hash + From {} - - impl HaltReasonTrait for HaltReasonT where - HaltReasonT: Clone + Debug + PartialEq + Eq + Hash + From - { - } - } +impl HaltReasonTrait for HaltReasonT where + HaltReasonT: Clone + Debug + PartialEq + Eq + From +{ } pub trait TransactionValidation { diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 852266b5d7..4ea4023c62 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -16,7 +16,6 @@ pub type EVMResultGeneric = core::result::Result< >; #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ResultAndState { /// Status of execution pub result: ExecutionResult, @@ -26,7 +25,6 @@ pub struct ResultAndState { /// Result of a transaction execution. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ExecutionResult { /// Returned successfully Success { From 6a881fadd9df56a067d8fce7599002db6e6dbeda Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 14:37:38 +0000 Subject: [PATCH 08/59] refactor: allow moving of kind --- crates/primitives/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index ac9d163fb1..55b3ecdad9 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -9,7 +9,7 @@ pub trait Transaction { /// The gas price the sender is willing to pay. fn gas_price(&self) -> &U256; /// Returns what kind of transaction this is. - fn kind(&self) -> &TxKind; + fn kind(&self) -> TxKind; /// The value sent to the receiver of `TxKind::Call`. fn value(&self) -> &U256; /// Returns the input data of the transaction. From dab9e20e4f677f0434214627950f648d79d80d89 Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 14:40:27 +0000 Subject: [PATCH 09/59] refactor: rename Transaction::nonce to nonce_opt to signal that it's optional --- crates/interpreter/src/interpreter/contract.rs | 4 ++-- crates/interpreter/src/interpreter_action/call_inputs.rs | 2 +- crates/primitives/src/env.rs | 8 ++++---- crates/primitives/src/transaction.rs | 2 +- crates/revm/src/context/evm_context.rs | 2 +- crates/revm/src/optimism/env.rs | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 9243d04892..53ca74e3f4 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -61,11 +61,11 @@ impl Contract { hash: Option, ) -> Self { let contract_address = match env.tx.kind() { - TxKind::Call(caller) => *caller, + TxKind::Call(caller) => caller, TxKind::Create => Address::ZERO, }; let bytecode_address = match env.tx.kind() { - TxKind::Call(caller) => Some(*caller), + TxKind::Call(caller) => Some(caller), TxKind::Create => None, }; Self::new( diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index d5ad291485..7695bd8980 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -49,7 +49,7 @@ impl CallInputs { /// /// Returns `None` if the transaction is not a call. pub fn new(tx_env: &impl Transaction, gas_limit: u64) -> Option { - let TxKind::Call(target_address) = *tx_env.kind() else { + let TxKind::Call(target_address) = tx_env.kind() else { return None; }; Some(CallInputs { diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 78550067ee..f24a124754 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -222,7 +222,7 @@ impl Env { } // Check that the transaction's nonce is correct - if let Some(tx) = self.tx.nonce() { + if let Some(tx) = self.tx.nonce_opt() { let state = account.info.nonce; match tx.cmp(&state) { Ordering::Greater => { @@ -619,8 +619,8 @@ impl Transaction for TxEnv { } #[inline] - fn kind(&self) -> &TransactTo { - &self.transact_to + fn kind(&self) -> TxKind { + self.transact_to } #[inline] @@ -634,7 +634,7 @@ impl Transaction for TxEnv { } #[inline] - fn nonce(&self) -> Option { + fn nonce_opt(&self) -> Option { self.nonce } diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index 55b3ecdad9..e69fdac0fb 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -19,7 +19,7 @@ pub trait Transaction { /// Caution: If set to `None`, then nonce validation against the account's /// nonce is skipped: [`crate::InvalidTransaction::NonceTooHigh`] and /// [`crate::InvalidTransaction::NonceTooLow`] - fn nonce(&self) -> Option; + fn nonce_opt(&self) -> Option; /// The chain ID of the transaction. If set to `None`, no checks are performed. /// /// Incorporated as part of the Spurious Dragon upgrade via [EIP-155]. diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 9eccab976b..15cff1e3a6 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -376,7 +376,7 @@ impl EvmContext { let nonce = self .env .tx - .nonce() + .nonce_opt() .map(|nonce| self.env.tx.caller().create(nonce)); (input, eof, nonce) diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index 5d6e9ea75c..e2de298b4b 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -127,7 +127,7 @@ impl Transaction for OptimismTransaction { self.base.gas_price() } - fn kind(&self) -> &TxKind { + fn kind(&self) -> TxKind { self.base.kind() } @@ -139,8 +139,8 @@ impl Transaction for OptimismTransaction { self.base.data() } - fn nonce(&self) -> Option { - self.base.nonce() + fn nonce_opt(&self) -> Option { + self.base.nonce_opt() } fn chain_id(&self) -> Option { From 214c1d5979eefae978fb5c43ddab734ec85e58a5 Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 22:04:35 +0000 Subject: [PATCH 10/59] refactor: replace AccessList with alloy version --- crates/revm/src/handler/mainnet/validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index 3946a4b7b0..c7c64392f8 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -75,7 +75,7 @@ where { let input = &env.tx.data(); let is_create = env.tx.kind().is_create(); - let access_list = &env.tx.access_list(); + let access_list = env.tx.access_list(); let authorization_list_num = env .tx .authorization_list() From 73035871e0075476b739600d1f9251515d789802 Mon Sep 17 00:00:00 2001 From: Wodann Date: Thu, 20 Jun 2024 03:56:36 +0000 Subject: [PATCH 11/59] refactor: rename gas_priority_fee to max_priority_fee_per_gas --- crates/primitives/src/env.rs | 6 +++--- crates/primitives/src/transaction.rs | 4 ++-- crates/revm/src/optimism/env.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index f24a124754..832661cf73 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -41,7 +41,7 @@ impl Env { #[inline] pub fn effective_gas_price(&self) -> U256 { let gas_price = self.tx.gas_price(); - if let Some(priority_fee) = self.tx.gas_priority_fee() { + if let Some(priority_fee) = self.tx.max_priority_fee_per_gas() { min(*gas_price, self.block.basefee() + priority_fee) } else { *gas_price @@ -115,7 +115,7 @@ impl Env { // BASEFEE tx check if SPEC::enabled(SpecId::LONDON) { - if let Some(priority_fee) = self.tx.gas_priority_fee() { + if let Some(priority_fee) = self.tx.max_priority_fee_per_gas() { if priority_fee > self.tx.gas_price() { // or gas_max_fee for eip1559 return Err(InvalidTransaction::PriorityFeeGreaterThanMaxFee); @@ -649,7 +649,7 @@ impl Transaction for TxEnv { } #[inline] - fn gas_priority_fee(&self) -> Option<&U256> { + fn max_priority_fee_per_gas(&self) -> Option<&U256> { self.gas_priority_fee.as_ref() } diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index e69fdac0fb..5d90c4e442 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -32,12 +32,12 @@ pub trait Transaction { /// /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 fn access_list(&self) -> &[AccessListItem]; - /// The priority fee per gas. + /// The maximum priority fee per gas the sender is willing to pay. /// /// Incorporated as part of the London upgrade via [EIP-1559]. /// /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 - fn gas_priority_fee(&self) -> Option<&U256>; + fn max_priority_fee_per_gas(&self) -> Option<&U256>; /// The list of blob versioned hashes. Per EIP there should be at least /// one blob present if [`Self::max_fee_per_blob_gas`] is `Some`. /// diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index e2de298b4b..ef87f5be72 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -151,8 +151,8 @@ impl Transaction for OptimismTransaction { self.base.access_list() } - fn gas_priority_fee(&self) -> Option<&U256> { - self.base.gas_priority_fee() + fn max_priority_fee_per_gas(&self) -> Option<&U256> { + self.base.max_priority_fee_per_gas() } fn blob_hashes(&self) -> &[B256] { From a8227c0a6d82c9fbb34ad9ea7f081e1c56074432 Mon Sep 17 00:00:00 2001 From: Wodann Date: Thu, 20 Jun 2024 18:04:48 +0000 Subject: [PATCH 12/59] refactor: correct trait bound on ExecutionResult::clone --- crates/primitives/src/result.rs | 30 ++++++++++++++++++- crates/revm/src/inspector/handler_register.rs | 3 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 4ea4023c62..74a69a07c9 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -24,7 +24,7 @@ pub struct ResultAndState { } /// Result of a transaction execution. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash)] pub enum ExecutionResult { /// Returned successfully Success { @@ -44,6 +44,34 @@ pub enum ExecutionResult { }, } +impl Clone for ExecutionResult { + fn clone(&self) -> Self { + match self { + Self::Success { + reason, + gas_used, + gas_refunded, + logs, + output, + } => Self::Success { + reason: *reason, + gas_used: *gas_used, + gas_refunded: *gas_refunded, + logs: logs.clone(), + output: output.clone(), + }, + Self::Revert { gas_used, output } => Self::Revert { + gas_used: *gas_used, + output: output.clone(), + }, + Self::Halt { reason, gas_used } => Self::Halt { + reason: reason.clone(), + gas_used: *gas_used, + }, + } + } +} + impl ExecutionResult { /// Returns if transaction execution is successful. /// 1 indicates success, 0 indicates revert. diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 6e34d72cb3..cc311fefa0 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -231,11 +231,12 @@ pub fn inspector_handle_register< }); } -fn inspector_instruction( +fn inspector_instruction( prev: &DynInstruction<'_, Context>, interpreter: &mut Interpreter, host: &mut Context, ) where + ChainSpecT: ChainSpec, INSP: GetInspector, DB: Database, { From fe1ab43bcf1b6f187397bd07a6f54de699022113 Mon Sep 17 00:00:00 2001 From: Wodann Date: Thu, 20 Jun 2024 19:36:47 +0000 Subject: [PATCH 13/59] Clone --- crates/revm/src/handler/cfg.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs index 7847c9731b..6dfcb7d81b 100644 --- a/crates/revm/src/handler/cfg.rs +++ b/crates/revm/src/handler/cfg.rs @@ -9,7 +9,7 @@ use derive_where::derive_where; use crate::primitives::{CfgEnv, ChainSpec, Env}; /// Configuration environment with the chain spec id. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq)] pub struct CfgEnvWithChainSpec { /// Configuration environment. pub cfg_env: CfgEnv, @@ -24,6 +24,15 @@ impl CfgEnvWithChainSpec { } } +impl Clone for CfgEnvWithChainSpec { + fn clone(&self) -> Self { + Self { + cfg_env: self.cfg_env.clone(), + spec_id: self.spec_id, + } + } +} + impl DerefMut for CfgEnvWithChainSpec { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.cfg_env From 373e19769d9f8e9ce57f66fe8f7a8607173488cd Mon Sep 17 00:00:00 2001 From: Wodann Date: Thu, 20 Jun 2024 19:37:12 +0000 Subject: [PATCH 14/59] refactor: only allow optional nonce check via CfgEnv --- crates/interpreter/Cargo.toml | 2 ++ crates/primitives/Cargo.toml | 2 ++ crates/primitives/src/env.rs | 28 ++++++++++++++++++++------ crates/primitives/src/transaction.rs | 6 +----- crates/revm/Cargo.toml | 2 ++ crates/revm/src/context/evm_context.rs | 13 ++++-------- crates/revm/src/optimism/env.rs | 4 ++-- examples/generate_block_traces.rs | 2 +- 8 files changed, 36 insertions(+), 23 deletions(-) diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 162c51190c..a4bdd081c0 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -61,6 +61,7 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", + "optional_nonce_check", ] memory_limit = ["revm-primitives/memory_limit"] optional_balance_check = ["revm-primitives/optional_balance_check"] @@ -69,5 +70,6 @@ optional_eip3607 = ["revm-primitives/optional_eip3607"] optional_gas_refund = ["revm-primitives/optional_gas_refund"] optional_no_base_fee = ["revm-primitives/optional_no_base_fee"] optional_beneficiary_reward = ["revm-primitives/optional_beneficiary_reward"] +optional_nonce_check = ["revm-primitives/optional_nonce_check"] kzg-rs = ["revm-primitives/kzg-rs"] diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 0a3832ff44..85249dae59 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -97,6 +97,7 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", + "optional_nonce_check", ] memory_limit = [] optional_balance_check = [] @@ -105,6 +106,7 @@ optional_eip3607 = [] optional_gas_refund = [] optional_no_base_fee = [] optional_beneficiary_reward = [] +optional_nonce_check = [] rand = ["alloy-primitives/rand"] # See comments in `revm-precompile` diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 832661cf73..c73707a8d6 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -222,7 +222,8 @@ impl Env { } // Check that the transaction's nonce is correct - if let Some(tx) = self.tx.nonce_opt() { + if !self.cfg.is_nonce_check_disabled() { + let tx = self.tx.nonce(); let state = account.info.nonce; match tx.cmp(&state) { Ordering::Greater => { @@ -328,6 +329,11 @@ pub struct CfgEnv { /// By default, it is set to `false`. #[cfg(feature = "optional_beneficiary_reward")] pub disable_beneficiary_reward: bool, + /// Skips the nonce validation against the account's nonce: + /// [`crate::InvalidTransaction::NonceTooHigh`] and + /// [`crate::InvalidTransaction::NonceTooLow`] + #[cfg(feature = "optional_nonce_check")] + pub disable_nonce_check: bool, } impl CfgEnv { @@ -401,6 +407,16 @@ impl CfgEnv { pub fn is_beneficiary_reward_disabled(&self) -> bool { false } + + #[cfg(feature = "optional_nonce_check")] + pub const fn is_nonce_check_disabled(&self) -> bool { + self.disable_nonce_check + } + + #[cfg(not(feature = "optional_nonce_check"))] + pub const fn is_nonce_check_disabled(&self) -> bool { + false + } } impl Default for CfgEnv { @@ -425,6 +441,8 @@ impl Default for CfgEnv { disable_base_fee: false, #[cfg(feature = "optional_beneficiary_reward")] disable_beneficiary_reward: false, + #[cfg(feature = "optional_nonce_check")] + disable_nonce_check: false, } } } @@ -553,9 +571,7 @@ pub struct TxEnv { pub data: Bytes, /// The nonce of the transaction. - /// - /// Caution: If set to `None`, then nonce validation against the account's nonce is skipped: [InvalidTransaction::NonceTooHigh] and [InvalidTransaction::NonceTooLow] - pub nonce: Option, + pub nonce: u64, /// The chain ID of the transaction. If set to `None`, no checks are performed. /// @@ -634,7 +650,7 @@ impl Transaction for TxEnv { } #[inline] - fn nonce_opt(&self) -> Option { + fn nonce(&self) -> u64 { self.nonce } @@ -691,7 +707,7 @@ impl Default for TxEnv { value: U256::ZERO, data: Bytes::new(), chain_id: None, - nonce: None, + nonce: 0, access_list: Vec::new(), blob_hashes: Vec::new(), max_fee_per_blob_gas: None, diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index 5d90c4e442..28452dfc74 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -15,11 +15,7 @@ pub trait Transaction { /// Returns the input data of the transaction. fn data(&self) -> &Bytes; /// The nonce of the transaction. - /// - /// Caution: If set to `None`, then nonce validation against the account's - /// nonce is skipped: [`crate::InvalidTransaction::NonceTooHigh`] and - /// [`crate::InvalidTransaction::NonceTooLow`] - fn nonce_opt(&self) -> Option; + fn nonce(&self) -> u64; /// The chain ID of the transaction. If set to `None`, no checks are performed. /// /// Incorporated as part of the Spurious Dragon upgrade via [EIP-155]. diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index a37d1a1e9b..173982973c 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -105,6 +105,7 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", + "optional_nonce_check", ] memory_limit = ["revm-interpreter/memory_limit"] optional_balance_check = ["revm-interpreter/optional_balance_check"] @@ -113,6 +114,7 @@ optional_eip3607 = ["revm-interpreter/optional_eip3607"] optional_gas_refund = ["revm-interpreter/optional_gas_refund"] optional_no_base_fee = ["revm-interpreter/optional_no_base_fee"] optional_beneficiary_reward = ["revm-interpreter/optional_beneficiary_reward"] +optional_nonce_check = ["revm-interpreter/optional_nonce_check"] # See comments in `revm-precompile` secp256k1 = ["revm-precompile/secp256k1"] diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 15cff1e3a6..8afb403bbc 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -371,15 +371,10 @@ impl EvmContext { return return_error(InstructionResult::InvalidEOFInitCode); } - // Use nonce from tx (if set) to calculate address. - // If not set, use the nonce from the account. - let nonce = self - .env - .tx - .nonce_opt() - .map(|nonce| self.env.tx.caller().create(nonce)); - - (input, eof, nonce) + // Use nonce from tx to calculate address. + let nonce = self.env.tx.nonce(); + + (input, eof, Some(self.env.tx.caller().create(nonce))) } }; diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index ef87f5be72..6d478be534 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -139,8 +139,8 @@ impl Transaction for OptimismTransaction { self.base.data() } - fn nonce_opt(&self) -> Option { - self.base.nonce_opt() + fn nonce(&self) -> u64 { + self.base.nonce() } fn chain_id(&self) -> Option { diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index ef98fa2580..099d24ddbb 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -124,7 +124,7 @@ async fn main() -> anyhow::Result<()> { ); etx.gas_priority_fee = Some(gas_priority_fee); etx.chain_id = Some(chain_id); - etx.nonce = Some(tx.nonce.as_u64()); + etx.nonce = tx.nonce.as_u64(); if let Some(access_list) = tx.access_list { etx.access_list = access_list .0 From 689be7fd64644919eabb1f3352ce03acc41f8810 Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 17:09:38 +0000 Subject: [PATCH 15/59] fix: revme --- bins/revme/src/cmd/evmrunner.rs | 20 ++++++++++++-------- bins/revme/src/cmd/statetest/runner.rs | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 86d3817a69..a8fd650a10 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -2,8 +2,8 @@ use revm::{ db::BenchmarkDB, inspector_handle_register, inspectors::TracerEip3155, - primitives::{eof::EofDecodeError, Address, Bytecode, TxKind}, - Evm, + primitives::{address, eof::EofDecodeError, Address, Bytecode, TxKind}, + Database, Evm, }; use std::io::Error as IoError; use std::path::PathBuf; @@ -57,6 +57,8 @@ pub struct Cmd { impl Cmd { /// Run evm runner command. pub fn run(&self) -> Result<(), Errors> { + const CALLER: Address = address!("0000000000000000000000000000000000000001"); + let bytecode_str: Cow<'_, str> = if let Some(path) = &self.path { // check if path exists. if !path.exists() { @@ -71,19 +73,21 @@ impl Cmd { let input = hex::decode(self.input.trim()) .map_err(|_| Errors::InvalidInput)? .into(); + + let mut db = BenchmarkDB::new_bytecode(Bytecode::new_raw_checked(bytecode.into())?); + + let nonce = db.basic(CALLER).unwrap().map_or(0, |account| account.nonce); + // BenchmarkDB is dummy state that implements Database trait. // the bytecode is deployed at zero address. let mut evm = Evm::builder() - .with_db(BenchmarkDB::new_bytecode(Bytecode::new_raw_checked( - bytecode.into(), - )?)) + .with_db(db) .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. - tx.caller = "0x0000000000000000000000000000000000000001" - .parse() - .unwrap(); + tx.caller = CALLER; tx.transact_to = TxKind::Call(Address::ZERO); tx.data = input; + tx.nonce = nonce; }) .build(); diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 5a9846257f..f61e359ee0 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -341,6 +341,8 @@ pub fn execute_test_suite( .get(test.indexes.data) .unwrap() .clone(); + + env.tx.nonce = u64::try_from(unit.transaction.nonce).unwrap(); env.tx.value = unit.transaction.value[test.indexes.value]; env.tx.access_list = unit From f53a2a9e9342ca9b88600af76149cd8809e75153 Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 17:58:25 +0000 Subject: [PATCH 16/59] refactor: derive DummyHost --- crates/interpreter/src/host/dummy.rs | 46 ++-------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index b4083308eb..c398f1a932 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,15 +1,17 @@ +use derive_where::derive_where; + use crate::{ primitives::{ hash_map::Entry, Address, Bytes, ChainSpec, Env, HashMap, Log, B256, KECCAK_EMPTY, U256, }, Host, SStoreResult, SelfDestructResult, }; -use core::fmt::Debug; use std::vec::Vec; use super::LoadAccountResult; /// A dummy [Host] implementation. +#[derive_where(Clone, Debug, Default; ChainSpecT::Block, ChainSpecT::Transaction)] pub struct DummyHost where ChainSpecT: ChainSpec, @@ -43,48 +45,6 @@ where } } -impl Clone for DummyHost -where - ChainSpecT: ChainSpec, -{ - fn clone(&self) -> Self { - Self { - env: self.env.clone(), - storage: self.storage.clone(), - transient_storage: self.transient_storage.clone(), - log: self.log.clone(), - } - } -} - -impl Debug for DummyHost -where - ChainSpecT: ChainSpec, -{ - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("DummyHost") - .field("env", &self.env) - .field("storage", &self.storage) - .field("transient_storage", &self.transient_storage) - .field("log", &self.log) - .finish() - } -} - -impl Default for DummyHost -where - ChainSpecT: ChainSpec, -{ - fn default() -> Self { - Self { - env: Env::default(), - storage: HashMap::new(), - transient_storage: HashMap::new(), - log: Vec::new(), - } - } -} - impl Host for DummyHost where ChainSpecT: ChainSpec, From dbe9e3a1a28dabd36e0b6ec6b433717c30a0c2cc Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 18:09:29 +0000 Subject: [PATCH 17/59] refactor: derive Clone for ExecutionResult --- crates/primitives/src/result.rs | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 74a69a07c9..f1d7fe0cce 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,3 +1,5 @@ +use derive_where::derive_where; + use crate::{Address, Bytes, ChainSpec, EvmState, Log, TransactionValidation, U256}; use core::fmt::{self, Debug}; use std::{boxed::Box, string::String, vec::Vec}; @@ -25,6 +27,7 @@ pub struct ResultAndState { /// Result of a transaction execution. #[derive(Debug, PartialEq, Eq, Hash)] +#[derive_where(Clone; ChainSpecT::HaltReason)] pub enum ExecutionResult { /// Returned successfully Success { @@ -44,34 +47,6 @@ pub enum ExecutionResult { }, } -impl Clone for ExecutionResult { - fn clone(&self) -> Self { - match self { - Self::Success { - reason, - gas_used, - gas_refunded, - logs, - output, - } => Self::Success { - reason: *reason, - gas_used: *gas_used, - gas_refunded: *gas_refunded, - logs: logs.clone(), - output: output.clone(), - }, - Self::Revert { gas_used, output } => Self::Revert { - gas_used: *gas_used, - output: output.clone(), - }, - Self::Halt { reason, gas_used } => Self::Halt { - reason: reason.clone(), - gas_used: *gas_used, - }, - } - } -} - impl ExecutionResult { /// Returns if transaction execution is successful. /// 1 indicates success, 0 indicates revert. From 77e19ce4594d5200cf5f5b79ac1483f480948954 Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 18:09:51 +0000 Subject: [PATCH 18/59] refactor: remove EVMErrorForChain --- crates/primitives/src/result.rs | 5 --- crates/revm/src/context/evm_context.rs | 17 ++++------ crates/revm/src/evm.rs | 34 ++++--------------- .../handler/handle_types/post_execution.rs | 8 ++--- .../src/handler/mainnet/post_execution.rs | 14 ++++---- 5 files changed, 23 insertions(+), 55 deletions(-) diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index f1d7fe0cce..6e0a0c43e2 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -175,11 +175,6 @@ impl EVMError = EVMError< - DBError, - <::Transaction as TransactionValidation>::ValidationError, ->; - #[cfg(feature = "std")] impl std::error::Error for EVMError diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 8afb403bbc..84444f0766 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -10,10 +10,11 @@ use crate::{ EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, primitives::{ - keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, EVMErrorForChain, - Env, Eof, + keccak256, + result::EVMResultGeneric, + Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, Env, Eof, SpecId::{self, *}, - Transaction as _, TransactionValidation, B256, EOF_MAGIC_BYTES, + Transaction as _, B256, EOF_MAGIC_BYTES, }, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; @@ -95,7 +96,7 @@ impl EvmContext { address: &Address, input_data: &Bytes, gas: Gas, - ) -> Result, EVMErrorForChain> { + ) -> EVMResultGeneric, ChainSpecT, DB::Error> { let Some(outcome) = self.precompiles .call(address, input_data, gas.limit(), &mut self.inner) @@ -135,13 +136,7 @@ impl EvmContext { pub fn make_call_frame( &mut self, inputs: &CallInputs, - ) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 6cce8118ff..e8f8b45b07 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,8 +6,8 @@ use crate::{ handler::{EnvWithChainSpec, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, ChainSpec, EVMError, EVMErrorForChain, EVMResult, EthChainSpec, ExecutionResult, - ResultAndState, SpecId, Transaction as _, TransactionValidation, TxKind, EOF_MAGIC_BYTES, + result::EVMResultGeneric, CfgEnv, ChainSpec, EVMError, EVMResult, EthChainSpec, + ExecutionResult, ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, }; @@ -44,7 +44,7 @@ impl Evm<'_, ChainSpe /// Commit the changes to the database. pub fn transact_commit( &mut self, - ) -> Result, EVMErrorForChain> { + ) -> EVMResultGeneric, ChainSpecT, DB::Error> { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) @@ -82,13 +82,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> pub fn run_the_loop( &mut self, first_frame: Frame, - ) -> Result< - FrameResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { let mut call_stack: Vec = Vec::with_capacity(1025); call_stack.push(first_frame); @@ -193,15 +187,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Pre verify transaction by checking Environment, initial gas spend and if caller /// has enough balance to pay for the gas. #[inline] - pub fn preverify_transaction( - &mut self, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + pub fn preverify_transaction(&mut self) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { let output = self.preverify_transaction_inner().map(|_| ()); self.clear(); output @@ -233,15 +219,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Pre verify transaction inner. #[inline] - fn preverify_transaction_inner( - &mut self, - ) -> Result< - u64, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + fn preverify_transaction_inner(&mut self) -> EVMResultGeneric { self.handler.validation().env(&self.context.evm.env)?; let initial_gas_spend = self .handler diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index 476cad73d7..a92aea7a9b 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -3,7 +3,7 @@ use crate::{ handler::mainnet, interpreter::Gas, primitives::{ - db::Database, ChainSpec, EVMError, EVMErrorForChain, EVMResultGeneric, ResultAndState, + db::Database, ChainSpec, EVMError, EVMResultGeneric, ResultAndState, Spec, TransactionValidation, }, Context, FrameResult, @@ -121,7 +121,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, result: FrameResult, - ) -> Result, EVMErrorForChain> { + ) -> EVMResultGeneric, ChainSpecT, DB::Error> { (self.output)(context, result) } @@ -129,8 +129,8 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai pub fn end( &self, context: &mut Context, - end_output: Result, EVMErrorForChain>, - ) -> Result, EVMErrorForChain> { + end_output: EVMResultGeneric, ChainSpecT, DB::Error>, + ) -> EVMResultGeneric, ChainSpecT, DB::Error> { (self.end)(context, end_output) } diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index fe50fad9b8..ed04327420 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,9 +1,9 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, Block, Bytecode, ChainSpec, EVMError, EVMErrorForChain, ExecutionResult, - ResultAndState, Spec, SpecId::LONDON, Transaction, TransactionValidation, KECCAK_EMPTY, - U256, + db::Database, result::EVMResultGeneric, Block, Bytecode, ChainSpec, EVMError, + ExecutionResult, ResultAndState, Spec, SpecId::LONDON, Transaction, TransactionValidation, + KECCAK_EMPTY, U256, }, Context, FrameResult, }; @@ -12,8 +12,8 @@ use crate::{ #[inline] pub fn end( _context: &mut Context, - evm_output: Result, EVMErrorForChain>, -) -> Result, EVMErrorForChain> { + evm_output: EVMResultGeneric, ChainSpecT, DB::Error>, +) -> EVMResultGeneric, ChainSpecT, DB::Error> { evm_output } @@ -71,7 +71,7 @@ pub fn reward_beneficiary( pub fn reimburse_caller( context: &mut Context, gas: &Gas, -) -> Result<(), EVMErrorForChain> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { let caller = context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -96,7 +96,7 @@ pub fn reimburse_caller( pub fn output( context: &mut Context, result: FrameResult, -) -> Result, EVMErrorForChain> { +) -> EVMResultGeneric, ChainSpecT, DB::Error> { context.evm.take_error().map_err(EVMError::Database)?; // used gas with refund calculated. From 6c16bef5e7727fea5f1c15ddf4dd89d8165f2022 Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 18:21:38 +0000 Subject: [PATCH 19/59] refactor: derive Clone for CfgEnvWithChainSpec --- crates/revm/src/handler/cfg.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs index 6dfcb7d81b..bc64c24724 100644 --- a/crates/revm/src/handler/cfg.rs +++ b/crates/revm/src/handler/cfg.rs @@ -10,6 +10,7 @@ use crate::primitives::{CfgEnv, ChainSpec, Env}; /// Configuration environment with the chain spec id. #[derive(Debug, Eq, PartialEq)] +#[derive_where(Clone; ChainSpecT::Hardfork)] pub struct CfgEnvWithChainSpec { /// Configuration environment. pub cfg_env: CfgEnv, @@ -24,15 +25,6 @@ impl CfgEnvWithChainSpec { } } -impl Clone for CfgEnvWithChainSpec { - fn clone(&self) -> Self { - Self { - cfg_env: self.cfg_env.clone(), - spec_id: self.spec_id, - } - } -} - impl DerefMut for CfgEnvWithChainSpec { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.cfg_env From 145a4ce7dcd17dda27f3b7aa22ef23b229323e5f Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 18:26:08 +0000 Subject: [PATCH 20/59] refactor: use EVMResultGeneric --- crates/revm/src/context/evm_context.rs | 5 +- crates/revm/src/evm.rs | 4 +- crates/revm/src/handler.rs | 10 +- .../src/handler/handle_types/execution.rs | 189 ++++-------------- .../handler/handle_types/post_execution.rs | 35 +--- .../src/handler/handle_types/pre_execution.rs | 29 +-- .../src/handler/handle_types/validation.rs | 62 +----- crates/revm/src/handler/mainnet/execution.rs | 90 ++------- .../src/handler/mainnet/post_execution.rs | 13 +- .../revm/src/handler/mainnet/pre_execution.rs | 20 +- crates/revm/src/handler/mainnet/validation.rs | 28 +-- crates/revm/src/inspector/handler_register.rs | 12 +- 12 files changed, 89 insertions(+), 408 deletions(-) diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 84444f0766..f1a285cb74 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -10,9 +10,8 @@ use crate::{ EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, primitives::{ - keccak256, - result::EVMResultGeneric, - Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, Env, Eof, + keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, EVMResultGeneric, + Env, Eof, SpecId::{self, *}, Transaction as _, B256, EOF_MAGIC_BYTES, }, diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index e8f8b45b07..e33fc90e42 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,8 +6,8 @@ use crate::{ handler::{EnvWithChainSpec, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - result::EVMResultGeneric, CfgEnv, ChainSpec, EVMError, EVMResult, EthChainSpec, - ExecutionResult, ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, + CfgEnv, ChainSpec, EVMError, EVMResult, EVMResultGeneric, EthChainSpec, ExecutionResult, + ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, }; diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 6dc457d18f..18dba994b4 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -12,7 +12,7 @@ pub use handle_types::*; use crate::{ interpreter::{opcode::InstructionTables, Host, InterpreterAction, SharedMemory}, primitives::{ - db::Database, spec_to_generic, ChainSpec, EVMError, InvalidTransaction, + db::Database, spec_to_generic, ChainSpec, EVMResultGeneric, InvalidTransaction, TransactionValidation, }, Context, Frame, @@ -82,13 +82,7 @@ where frame: &mut Frame, shared_memory: &mut SharedMemory, context: &mut Context, - ) -> Result< - InterpreterAction, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { self.execution .execute_frame(frame, shared_memory, &self.instruction_table, context) } diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index 3cdc7d1369..f5bd8cac3e 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -2,7 +2,7 @@ use crate::{ frame::EOFCreateFrame, handler::mainnet, interpreter::{CallInputs, CreateInputs, SharedMemory}, - primitives::{db::Database, ChainSpec, EVMError, Spec, TransactionValidation}, + primitives::{db::Database, ChainSpec, EVMResultGeneric, Spec}, CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ @@ -16,13 +16,8 @@ pub type LastFrameReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, &mut FrameResult, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, >; /// Executes a single frame. Errors can be returned in the EVM context. @@ -32,13 +27,8 @@ pub type ExecuteFrameHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut SharedMemory, &InstructionTables<'_, Context>, &mut Context, - ) -> Result< - InterpreterAction, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Handle sub call. @@ -46,13 +36,8 @@ pub type FrameCallHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, Box, - ) -> Result< - FrameOrResult, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Handle call return @@ -61,13 +46,8 @@ pub type FrameCallReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result< - CallOutcome, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Insert call outcome to the parent @@ -77,13 +57,8 @@ pub type InsertCallOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Frame, &mut SharedMemory, CallOutcome, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, >; /// Handle sub create. @@ -91,13 +66,8 @@ pub type FrameCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, Box, - ) -> Result< - FrameOrResult, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Handle create return @@ -106,13 +76,8 @@ pub type FrameCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result< - CreateOutcome, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Insert call outcome to the parent @@ -121,13 +86,8 @@ pub type InsertCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, &mut Frame, CreateOutcome, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, >; /// Handle EOF sub create. @@ -135,13 +95,8 @@ pub type FrameEOFCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, Box, - ) -> Result< - FrameOrResult, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Handle EOF create return @@ -150,13 +105,8 @@ pub type FrameEOFCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result< - CreateOutcome, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric::Error> + + 'a, >; /// Insert EOF crate outcome to the parent @@ -165,13 +115,8 @@ pub type InsertEOFCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< &mut Context, &mut Frame, CreateOutcome, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, >; /// Handles related to stack frames. @@ -231,13 +176,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe shared_memory: &mut SharedMemory, instruction_tables: &InstructionTables<'_, Context>, context: &mut Context, - ) -> Result< - InterpreterAction, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.execute_frame)(frame, shared_memory, instruction_tables, context) } @@ -247,13 +186,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, frame_result: &mut FrameResult, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.last_frame_return)(context, frame_result) } @@ -263,13 +196,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, inputs: Box, - ) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.call)(context, inputs) } @@ -280,13 +207,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result< - CallOutcome, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.call_return)(context, frame, interpreter_result) } @@ -298,13 +219,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.insert_call_outcome)(context, frame, shared_memory, outcome) } @@ -314,13 +229,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, inputs: Box, - ) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.create)(context, inputs) } @@ -331,13 +240,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result< - CreateOutcome, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.create_return)(context, frame, interpreter_result) } @@ -348,13 +251,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.insert_create_outcome)(context, frame, outcome) } @@ -364,13 +261,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe &self, context: &mut Context, inputs: Box, - ) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.eofcreate)(context, inputs) } @@ -381,13 +272,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result< - CreateOutcome, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.eofcreate_return)(context, frame, interpreter_result) } @@ -398,13 +283,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.insert_eofcreate_outcome)(context, frame, outcome) } } diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index a92aea7a9b..fa391bac1e 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -2,10 +2,7 @@ use crate::{ handler::mainnet, interpreter::Gas, - primitives::{ - db::Database, ChainSpec, EVMError, EVMResultGeneric, ResultAndState, - Spec, TransactionValidation, - }, + primitives::{db::Database, ChainSpec, EVMResultGeneric, ResultAndState, Spec}, Context, FrameResult, }; use std::sync::Arc; @@ -28,13 +25,9 @@ pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, FrameResult, - ) -> Result< - ResultAndState, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) + -> EVMResultGeneric, ChainSpecT, ::Error> + + 'a, >; /// End handle, takes result and state and returns final result. @@ -44,9 +37,9 @@ pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< pub type EndHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, - Result, EVMError<::Error, <::Transaction as TransactionValidation>::ValidationError>>, + EVMResultGeneric, ChainSpecT, ::Error>, ) - -> Result, EVMError<::Error, <::Transaction as TransactionValidation>::ValidationError>> + -> EVMResultGeneric, ChainSpecT, ::Error> + 'a, >; @@ -92,13 +85,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, gas: &Gas, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.reimburse_caller)(context, gas) } /// Reward beneficiary @@ -106,13 +93,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, Chai &self, context: &mut Context, gas: &Gas, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.reward_beneficiary)(context, gas) } diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 2f54ddd80f..40527752c0 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -1,9 +1,7 @@ // Includes. use crate::{ handler::mainnet, - primitives::{ - db::Database, ChainSpec, EVMError, EVMResultGeneric, Spec, TransactionValidation, - }, + primitives::{db::Database, ChainSpec, EVMResultGeneric, Spec}, Context, ContextPrecompiles, }; use std::sync::Arc; @@ -18,13 +16,8 @@ pub type LoadPrecompilesHandle<'a, ChainSpecT, DB> = pub type LoadAccountsHandle<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, >; /// Deduct the caller to its limit. @@ -63,13 +56,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PreExecutionHandler<'a, Chain pub fn deduct_caller( &self, context: &mut Context, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.deduct_caller)(context) } @@ -77,13 +64,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PreExecutionHandler<'a, Chain pub fn load_accounts( &self, context: &mut Context, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.load_accounts)(context) } diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index c12e711804..df00f724b0 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -1,50 +1,29 @@ use crate::{ handler::mainnet, primitives::{ - db::Database, ChainSpec, EVMError, Env, InvalidTransaction, Spec, TransactionValidation, + db::Database, ChainSpec, EVMResultGeneric, Env, InvalidTransaction, Spec, + TransactionValidation, }, Context, }; use std::sync::Arc; /// Handle that validates env. -pub type ValidateEnvHandle<'a, ChainSpecT, DB> = Arc< - dyn Fn( - &Env, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, ->; +pub type ValidateEnvHandle<'a, ChainSpecT, DB> = + Arc) -> EVMResultGeneric<(), ChainSpecT, ::Error> + 'a>; /// Handle that validates transaction environment against the state. /// Second parametar is initial gas. pub type ValidateTxEnvAgainstState<'a, ChainSpecT, EXT, DB> = Arc< dyn Fn( &mut Context, - ) -> Result< - (), - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + + 'a, >; /// Initial gas calculation handle pub type ValidateInitialTxGasHandle<'a, ChainSpecT, DB> = Arc< - dyn Fn( - &Env, - ) -> Result< - u64, - EVMError< - ::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > + 'a, + dyn Fn(&Env) -> EVMResultGeneric::Error> + 'a, >; /// Handles related to validation. @@ -76,16 +55,7 @@ where impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSpecT, EXT, DB> { /// Validate env. - pub fn env( - &self, - env: &Env, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + pub fn env(&self, env: &Env) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.env)(env) } @@ -93,13 +63,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSp pub fn initial_tx_gas( &self, env: &Env, - ) -> Result< - u64, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric { (self.initial_tx_gas)(env) } @@ -107,13 +71,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSp pub fn tx_against_state( &self, context: &mut Context, - ) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { (self.tx_against_state)(context) } } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index f98d24f510..649c02fcd3 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -5,7 +5,7 @@ use crate::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, SharedMemory, }, - primitives::{ChainSpec, EVMError, Env, Spec, SpecId, Transaction, TransactionValidation}, + primitives::{ChainSpec, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction}, CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use core::mem; @@ -22,13 +22,7 @@ pub fn execute_frame( shared_memory: &mut SharedMemory, instruction_tables: &InstructionTables<'_, Context>, context: &mut Context, -) -> Result< - InterpreterAction, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { let interpreter = frame.interpreter_mut(); let memory = mem::replace(shared_memory, EMPTY_SHARED_MEMORY); let next_action = match instruction_tables { @@ -82,13 +76,7 @@ pub fn frame_return_with_refund_flag( pub fn last_frame_return( context: &mut Context, frame_result: &mut FrameResult, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { frame_return_with_refund_flag::(&context.evm.env, frame_result, true); Ok(()) } @@ -98,13 +86,7 @@ pub fn last_frame_return( pub fn call( context: &mut Context, inputs: Box, -) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { context.evm.make_call_frame(&inputs) } @@ -113,13 +95,7 @@ pub fn call_return( context: &mut Context, frame: Box, interpreter_result: InterpreterResult, -) -> Result< - CallOutcome, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { context .evm .call_return(&interpreter_result, frame.frame_data.checkpoint); @@ -135,13 +111,7 @@ pub fn insert_call_outcome( frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -156,13 +126,7 @@ pub fn insert_call_outcome( pub fn create( context: &mut Context, inputs: Box, -) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { context .evm .make_create_frame(SPEC::SPEC_ID, &inputs) @@ -174,13 +138,7 @@ pub fn create_return( context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result< - CreateOutcome, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { context.evm.create_return::( &mut interpreter_result, frame.created_address, @@ -197,13 +155,7 @@ pub fn insert_create_outcome( context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -218,13 +170,7 @@ pub fn insert_create_outcome( pub fn eofcreate( context: &mut Context, inputs: Box, -) -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { context .evm .make_eofcreate_frame(SPEC::SPEC_ID, &inputs) @@ -236,13 +182,7 @@ pub fn eofcreate_return( context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result< - CreateOutcome, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric { context.evm.eofcreate_return::( &mut interpreter_result, frame.created_address, @@ -259,13 +199,7 @@ pub fn insert_eofcreate_outcome( context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { core::mem::replace(&mut context.evm.error, Ok(())).map_err(EVMError::Database)?; frame diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index ed04327420..871a06f666 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,9 +1,8 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, result::EVMResultGeneric, Block, Bytecode, ChainSpec, EVMError, - ExecutionResult, ResultAndState, Spec, SpecId::LONDON, Transaction, TransactionValidation, - KECCAK_EMPTY, U256, + db::Database, Block, Bytecode, ChainSpec, EVMError, EVMResultGeneric, ExecutionResult, + ResultAndState, Spec, SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, }, Context, FrameResult, }; @@ -33,13 +32,7 @@ pub fn clear(context: &mut Context( context: &mut Context, gas: &Gas, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { let beneficiary = *context.evm.env.block.coinbase(); let effective_gas_price = context.evm.env.effective_gas_price(); diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 8858434adc..827f8d38dd 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -5,8 +5,8 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ - db::Database, Account, Block, ChainSpec, EVMError, Env, Spec, SpecId, Transaction as _, - TransactionValidation, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, + db::Database, Account, Block, ChainSpec, EVMError, EVMResultGeneric, Env, Spec, SpecId, + Transaction as _, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, }; @@ -23,13 +23,7 @@ pub fn load_precompiles( #[inline] pub fn load_accounts( context: &mut Context, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { // set journaling state flag. context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); @@ -162,13 +156,7 @@ pub fn deduct_caller_inner( #[inline] pub fn deduct_caller( context: &mut Context, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> { +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { // load caller's account. let (caller_account, _) = context .evm diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index c7c64392f8..1b50e4fe0a 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -2,8 +2,8 @@ use revm_interpreter::gas; use crate::{ primitives::{ - db::Database, ChainSpec, EVMError, Env, InvalidTransaction, Spec, Transaction, - TransactionValidation, + db::Database, ChainSpec, EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, + Transaction, TransactionValidation, }, Context, }; @@ -11,13 +11,7 @@ use crate::{ /// Validate environment for the mainnet. pub fn validate_env( env: &Env, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> where ::ValidationError: From, { @@ -31,13 +25,7 @@ where /// Validates transaction against the state. pub fn validate_tx_against_state( context: &mut Context, -) -> Result< - (), - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> where ::ValidationError: From, { @@ -63,13 +51,7 @@ where /// Validate initial transaction gas. pub fn validate_initial_tx_gas( env: &Env, -) -> Result< - u64, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, -> +) -> EVMResultGeneric where ::ValidationError: From, { diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index cc311fefa0..07c8ce9bc2 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -2,7 +2,7 @@ use crate::{ db::Database, handler::register::EvmHandler, interpreter::{opcode, InstructionResult, Interpreter}, - primitives::{ChainSpec, EVMError, TransactionValidation}, + primitives::{ChainSpec, EVMResultGeneric}, Context, FrameOrResult, FrameResult, Inspector, JournalEntry, }; use core::cell::RefCell; @@ -96,15 +96,7 @@ pub fn inspector_handle_register< let create_input_stack_inner = create_input_stack.clone(); let prev_handle = handler.execution.create.clone(); handler.execution.create = Arc::new( - move |ctx, - mut inputs| - -> Result< - FrameOrResult, - EVMError< - DB::Error, - <::Transaction as TransactionValidation>::ValidationError, - >, - > { + move |ctx, mut inputs| -> EVMResultGeneric { let inspector = ctx.external.get_inspector(); // call inspector create to change input or return outcome. if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { From 3f29a23e62dfca3a986c357ef913c82e3bc1f0c3 Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 24 Jun 2024 18:57:17 +0000 Subject: [PATCH 21/59] refactor: add convenience EVMErrorForChain type alias --- crates/primitives/src/result.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 6e0a0c43e2..f3de017438 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -9,12 +9,13 @@ pub type EVMResult = EVMResultGeneric, ChainSpecT, DBError>; /// Generic result of EVM execution. Used to represent error and generic output. -pub type EVMResultGeneric = core::result::Result< - T, - EVMError< - DBError, - <::Transaction as TransactionValidation>::ValidationError, - >, +pub type EVMResultGeneric = + core::result::Result>; + +/// EVM error type for a specific chain. +pub type EVMErrorForChain = EVMError< + DBError, + <::Transaction as TransactionValidation>::ValidationError, >; #[derive(Debug, Clone, PartialEq, Eq)] From 3c6c4d39e7d3558496251bec2396615a8945ff5c Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 8 Jul 2024 19:52:17 +0000 Subject: [PATCH 22/59] feat: export OptimismBlock --- crates/revm/src/optimism.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index b2edd651ee..b3bca67bbe 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -8,6 +8,7 @@ mod l1block; mod result; mod spec; +pub use env::OptimismBlock; pub use handler_register::{ deduct_caller, end, last_frame_return, load_precompiles, optimism_handle_register, output, reward_beneficiary, validate_env, validate_tx_against_state, From 4856bea758dbd2d154b29857f2c56a3e045e7c6b Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 22 Jul 2024 17:33:41 +0000 Subject: [PATCH 23/59] refactor: add handler constructor and Context to revm::ChainSpec --- crates/revm/src/builder.rs | 98 +++----------- crates/revm/src/chain_spec.rs | 38 ++++++ crates/revm/src/context.rs | 36 +---- crates/revm/src/context/evm_context.rs | 20 ++- crates/revm/src/evm.rs | 6 +- crates/revm/src/handler.rs | 18 +-- .../src/handler/handle_types/execution.rs | 4 +- .../handler/handle_types/post_execution.rs | 4 +- .../src/handler/handle_types/pre_execution.rs | 4 +- .../src/handler/handle_types/validation.rs | 5 +- crates/revm/src/handler/mainnet/execution.rs | 4 +- .../src/handler/mainnet/post_execution.rs | 6 +- .../revm/src/handler/mainnet/pre_execution.rs | 4 +- crates/revm/src/handler/mainnet/validation.rs | 6 +- crates/revm/src/handler/register.rs | 2 +- crates/revm/src/inspector.rs | 4 +- crates/revm/src/inspector/customprinter.rs | 4 +- crates/revm/src/inspector/eip3155.rs | 4 +- crates/revm/src/inspector/gas.rs | 35 ++--- crates/revm/src/inspector/handler_register.rs | 32 ++--- crates/revm/src/inspector/noop.rs | 3 +- crates/revm/src/lib.rs | 2 + crates/revm/src/optimism.rs | 2 - crates/revm/src/optimism/env.rs | 84 +----------- crates/revm/src/optimism/handler.rs | 19 --- crates/revm/src/optimism/handler_register.rs | 128 ++++++++---------- crates/revm/src/optimism/result.rs | 10 -- crates/revm/src/optimism/spec.rs | 39 +++++- 28 files changed, 236 insertions(+), 385 deletions(-) create mode 100644 crates/revm/src/chain_spec.rs delete mode 100644 crates/revm/src/optimism/handler.rs diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index fe48720df1..4a5a2e065b 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,11 +1,8 @@ use crate::{ db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, - handler::{ - register::{self, EvmHandler}, - CfgEnvWithChainSpec, EnvWithChainSpec, - }, - primitives::{CfgEnv, ChainSpec, Env, EthChainSpec, InvalidTransaction, TransactionValidation}, - Context, ContextWithChainSpec, Evm, EvmContext, Handler, + handler::{register, CfgEnvWithChainSpec, EnvWithChainSpec}, + primitives::{self, CfgEnv, Env, EthChainSpec, InvalidTransaction, TransactionValidation}, + ChainSpec, Context, ContextWithChainSpec, Evm, EvmContext, Handler, }; use core::marker::PhantomData; use std::boxed::Box; @@ -33,8 +30,8 @@ impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthChainSpec, (), EmptyDB> fn default() -> Self { Self { context: Context::default(), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler( - ::Hardfork::default(), + handler: EthChainSpec::handler::<'a, (), EmptyDB>( + ::Hardfork::default(), ), phantom: PhantomData, } @@ -59,9 +56,7 @@ where EvmBuilder { context: Context::new(EvmContext::new(evm.inner.db), external), - handler: EvmBuilder::<'_, SetGenericStage, NewChainSpecT, _, _>::handler( - NewChainSpecT::Hardfork::default(), - ), + handler: NewChainSpecT::handler::<'a, EXT, DB>(NewChainSpecT::Hardfork::default()), phantom: PhantomData, } } @@ -79,7 +74,7 @@ where self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -90,7 +85,7 @@ where ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, ODB> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, EXT, ODB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -104,7 +99,7 @@ where self.context.evm.with_db(WrapDatabaseRef(db)), self.context.external, ), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), phantom: PhantomData, } } @@ -116,7 +111,7 @@ where ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, OEXT, DB> { EvmBuilder { context: Context::new(self.context.evm, external), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, OEXT, DB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -130,7 +125,7 @@ where self.context.evm.env = env; EvmBuilder { context: self.context, - handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler(spec_id), + handler: ChainSpecT::handler::<'a, EXT, DB>(spec_id), phantom: PhantomData, } } @@ -142,9 +137,7 @@ where ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, OEXT, ODB> { EvmBuilder { context: context_with_handler_cfg.context, - handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler( - context_with_handler_cfg.spec_id, - ), + handler: ChainSpecT::handler::<'a, OEXT, ODB>(context_with_handler_cfg.spec_id), phantom: PhantomData, } } @@ -158,7 +151,7 @@ where EvmBuilder { context: self.context, - handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler(cfg_env_and_spec_id.spec_id), + handler: ChainSpecT::handler::<'a, EXT, DB>(cfg_env_and_spec_id.spec_id), phantom: PhantomData, } } @@ -194,7 +187,7 @@ where self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: EvmBuilder::<'_, HandlerStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -207,7 +200,7 @@ where ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, ODB> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, EXT, ODB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -223,7 +216,7 @@ where self.context.evm.with_db(WrapDatabaseRef(db)), self.context.external, ), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), phantom: PhantomData, } } @@ -236,7 +229,7 @@ where ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, OEXT, DB> { EvmBuilder { context: Context::new(self.context.evm, external), - handler: EvmBuilder::<'_, SetGenericStage, _, _, _>::handler(self.handler.spec_id()), + handler: ChainSpecT::handler::<'a, OEXT, DB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -410,13 +403,6 @@ where ChainSpecT: ChainSpec>>, { - /// Creates the default handler. - /// - /// This is useful for adding optimism handle register. - fn handler(spec_id: ChainSpecT::Hardfork) -> EvmHandler<'a, ChainSpecT, EXT, DB> { - Handler::mainnet_with_spec(spec_id) - } - /// Sets specification Id , that will mark the version of EVM. /// It represent the hard fork of ethereum. /// @@ -436,7 +422,7 @@ where /// Resets [`Handler`] to default mainnet. pub fn reset_handler(mut self) -> Self { - self.handler = Self::handler(self.handler.spec_id()); + self.handler = ChainSpecT::handler::<'a, EXT, DB>(self.handler.spec_id()); self } } @@ -456,9 +442,6 @@ mod test { use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; - #[cfg(feature = "optimism")] - type TestChainSpec = crate::optimism::OptimismChainSpec; - #[cfg(not(feature = "optimism"))] type TestChainSpec = crate::primitives::EthChainSpec; /// Custom evm context @@ -485,9 +468,6 @@ mod test { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) .modify_tx_env(|tx| { - #[cfg(feature = "optimism")] - let transact_to = &mut tx.base.transact_to; - #[cfg(not(feature = "optimism"))] let transact_to = &mut tx.transact_to; *transact_to = TxKind::Call(to_addr) @@ -543,9 +523,6 @@ mod test { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) .modify_tx_env(|tx| { - #[cfg(feature = "optimism")] - let transact_to = &mut tx.base.transact_to; - #[cfg(not(feature = "optimism"))] let transact_to = &mut tx.transact_to; *transact_to = TxKind::Call(to_addr) @@ -594,49 +571,21 @@ mod test { Evm::builder() .with_chain_spec::() .with_empty_db() - .modify_tx_env(|tx| { - #[cfg(feature = "optimism")] - let gas_limit = &mut tx.base.gas_limit; - #[cfg(not(feature = "optimism"))] - let gas_limit = &mut tx.gas_limit; - - *gas_limit = 10 - }) + .modify_tx_env(|tx| tx.gas_limit = 10) .build(); Evm::builder() .with_chain_spec::() - .modify_tx_env(|tx| { - #[cfg(feature = "optimism")] - let gas_limit = &mut tx.base.gas_limit; - #[cfg(not(feature = "optimism"))] - let gas_limit = &mut tx.gas_limit; - - *gas_limit = 10 - }) + .modify_tx_env(|tx| tx.gas_limit = 10) .build(); Evm::builder() .with_chain_spec::() .with_empty_db() - .modify_tx_env(|tx| { - #[cfg(feature = "optimism")] - let gas_limit = &mut tx.base.gas_limit; - #[cfg(not(feature = "optimism"))] - let gas_limit = &mut tx.gas_limit; - - *gas_limit = 10 - }) + .modify_tx_env(|tx| tx.gas_limit = 10) .build(); Evm::builder() .with_chain_spec::() .with_empty_db() - .modify_tx_env(|tx| { - #[cfg(feature = "optimism")] - let gas_limit = &mut tx.base.gas_limit; - #[cfg(not(feature = "optimism"))] - let gas_limit = &mut tx.gas_limit; - - *gas_limit = 10 - }) + .modify_tx_env(|tx| tx.gas_limit = 10) .build(); // with inspector handle @@ -691,9 +640,6 @@ mod test { } } - #[cfg(feature = "optimism")] - let spec_id = crate::optimism::OptimismSpecId::HOMESTEAD; - #[cfg(not(feature = "optimism"))] let spec_id = crate::primitives::SpecId::HOMESTEAD; let mut evm = Evm::builder() diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs new file mode 100644 index 0000000000..e063d07827 --- /dev/null +++ b/crates/revm/src/chain_spec.rs @@ -0,0 +1,38 @@ +use crate::{ + handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, + interpreter::opcode::InstructionTables, + primitives::{db::Database, spec_to_generic, EthChainSpec}, + EvmHandler, +}; + +pub trait ChainSpec: crate::primitives::ChainSpec { + /// The type that contains all context information for the chain's EVM execution. + type Context: Default; + + /// Creates a new handler with the given hardfork. + fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> + where + DB: Database; +} + +impl ChainSpec for EthChainSpec { + type Context = (); + + fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> + where + DB: Database, + { + spec_to_generic!( + hardfork, + EvmHandler { + spec_id: hardfork, + instruction_table: InstructionTables::new_plain::(), + registers: Vec::new(), + validation: ValidationHandler::new::(), + pre_execution: PreExecutionHandler::new::(), + post_execution: PostExecutionHandler::mainnet::(), + execution: ExecutionHandler::new::(), + } + ) + } +} diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index fecb35a960..9b007c780f 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -6,6 +6,7 @@ pub use context_precompiles::{ ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, }; +use derive_where::derive_where; pub use evm_context::EvmContext; pub use inner_evm_context::InnerEvmContext; use revm_interpreter::as_usize_saturated; @@ -14,13 +15,14 @@ use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, primitives::{ - Address, Block as _, Bytes, ChainSpec, Env, EthChainSpec, Log, B256, BLOCK_HASH_HISTORY, - U256, + Address, Block as _, Bytes, Env, EthChainSpec, Log, B256, BLOCK_HASH_HISTORY, U256, }, + ChainSpec, }; use std::boxed::Box; /// Main Context structure that contains both EvmContext and External context. +#[derive_where(Clone; ChainSpecT::Block, ChainSpecT::Context, ChainSpecT::Transaction, DB, DB::Error, EXT)] pub struct Context { /// Evm Context (internal context). pub evm: EvmContext, @@ -28,21 +30,6 @@ pub struct Context { pub external: EXT, } -impl Clone for Context -where - DB::Error: Clone, - ChainSpecT: ChainSpec, - EXT: Clone, - DB: Database + Clone, -{ - fn clone(&self) -> Self { - Self { - evm: self.evm.clone(), - external: self.external.clone(), - } - } -} - impl Default for Context { fn default() -> Self { Self::new_empty() @@ -84,6 +71,7 @@ impl Context { } /// Context with handler configuration. +#[derive_where(Clone; ChainSpecT::Block, ChainSpecT::Context, ChainSpecT::Transaction, DB, DB::Error, EXT)] pub struct ContextWithChainSpec { /// Context of execution. pub context: Context, @@ -98,20 +86,6 @@ impl ContextWithChainSpec Clone for ContextWithChainSpec -where - ChainSpecT: ChainSpec, - EXT: Clone, - DB: Database + Clone, -{ - fn clone(&self) -> Self { - Self { - context: self.context.clone(), - spec_id: self.spec_id, - } - } -} - impl Host for Context { type ChainSpecT = ChainSpecT; diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index f1a285cb74..51024b0f50 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -10,19 +10,20 @@ use crate::{ EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, primitives::{ - keccak256, Address, Bytecode, Bytes, ChainSpec, CreateScheme, EVMError, EVMResultGeneric, - Env, Eof, + keccak256, Address, Bytecode, Bytes, CreateScheme, EVMError, EVMResultGeneric, Env, Eof, SpecId::{self, *}, Transaction as _, B256, EOF_MAGIC_BYTES, }, - ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, + ChainSpec, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; use core::ops::{Deref, DerefMut}; use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. -#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Transaction, DB, DB::Error)] +#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Context, ChainSpecT::Transaction, DB, DB::Error)] pub struct EvmContext { + /// The context that's unique to the chain type. + pub chain: ChainSpecT::Context, /// Inner EVM context. pub inner: InnerEvmContext, /// Precompiles that are available for evm. @@ -51,17 +52,23 @@ where /// Create new context with database. pub fn new(db: DB) -> Self { Self { + chain: ChainSpecT::Context::default(), inner: InnerEvmContext::new(db), precompiles: ContextPrecompiles::default(), } } } -impl EvmContext { +impl EvmContext +where + ChainSpecT: ChainSpec, + DB: Database, +{ /// Creates a new context with the given environment and database. #[inline] pub fn new_with_env(db: DB, env: Box>) -> Self { Self { + chain: ChainSpecT::Context::default(), inner: InnerEvmContext::new_with_env(db, env), precompiles: ContextPrecompiles::default(), } @@ -73,6 +80,7 @@ impl EvmContext { #[inline] pub fn with_db(self, db: ODB) -> EvmContext { EvmContext { + chain: self.chain, inner: self.inner.with_db(db), precompiles: ContextPrecompiles::default(), } @@ -494,6 +502,7 @@ pub(crate) mod test_utils { db: CacheDB, ) -> EvmContext> { EvmContext { + chain: ChainSpecT::Context::default(), inner: InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), @@ -511,6 +520,7 @@ pub(crate) mod test_utils { db: EmptyDB, ) -> EvmContext { EvmContext { + chain: ChainSpecT::Context::default(), inner: InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index e33fc90e42..d769db1022 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,10 +6,10 @@ use crate::{ handler::{EnvWithChainSpec, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, ChainSpec, EVMError, EVMResult, EVMResultGeneric, EthChainSpec, ExecutionResult, + CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthChainSpec, ExecutionResult, ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, }, - Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, + ChainSpec, Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, }; use core::fmt::{self, Debug}; use std::{boxed::Box, vec::Vec}; @@ -29,7 +29,7 @@ pub struct Evm<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { impl Debug for Evm<'_, ChainSpecT, EXT, DB> where - ChainSpecT: ChainSpec, + ChainSpecT: ChainSpec, EXT: Debug, DB: Database + Debug, { diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 18dba994b4..2185fc554b 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -12,10 +12,9 @@ pub use handle_types::*; use crate::{ interpreter::{opcode::InstructionTables, Host, InterpreterAction, SharedMemory}, primitives::{ - db::Database, spec_to_generic, ChainSpec, EVMResultGeneric, InvalidTransaction, - TransactionValidation, + db::Database, spec_to_generic, EVMResultGeneric, InvalidTransaction, TransactionValidation, }, - Context, Frame, + ChainSpec, Context, Frame, }; use core::mem; use register::{EvmHandler, HandleRegisters}; @@ -159,7 +158,7 @@ where let out = self.registers.pop(); if out.is_some() { let registers = core::mem::take(&mut self.registers); - let mut base_handler = Handler::mainnet_with_spec(self.spec_id); + let mut base_handler = ChainSpecT::handler::<'a, EXT, DB>(self.spec_id); // apply all registers to default handler and raw mainnet instruction table. for register in registers { base_handler.append_handler_register(register) @@ -177,7 +176,7 @@ where let registers = core::mem::take(&mut self.registers); // register for optimism is added as a register, so we need to create mainnet handler here. - let mut handler = Handler::mainnet_with_spec(spec_id); + let mut handler = ChainSpecT::handler::<'a, EXT, DB>(spec_id); // apply all registers to default handler and raw mainnet instruction table. for register in registers { handler.append_handler_register(register) @@ -191,7 +190,10 @@ where mod test { use core::cell::RefCell; - use crate::{db::EmptyDB, primitives::EVMError}; + use crate::{ + db::EmptyDB, + primitives::{self, EVMError}, + }; use std::{rc::Rc, sync::Arc}; use super::*; @@ -199,7 +201,7 @@ mod test { #[cfg(feature = "optimism")] type TestChainSpec = crate::optimism::OptimismChainSpec; #[cfg(not(feature = "optimism"))] - type TestChainSpec = crate::primitives::EthChainSpec; + type TestChainSpec = primitives::EthChainSpec; #[test] fn test_handler_register_pop() { @@ -214,7 +216,7 @@ mod test { }; let mut handler = EvmHandler::<'_, TestChainSpec, (), EmptyDB>::mainnet_with_spec( - ::Hardfork::default(), + ::Hardfork::default(), ); let test = Rc::new(RefCell::new(0)); diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index f5bd8cac3e..03dc4125a3 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -2,8 +2,8 @@ use crate::{ frame::EOFCreateFrame, handler::mainnet, interpreter::{CallInputs, CreateInputs, SharedMemory}, - primitives::{db::Database, ChainSpec, EVMResultGeneric, Spec}, - CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, + primitives::{db::Database, EVMResultGeneric, Spec}, + CallFrame, ChainSpec, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInputs, InterpreterAction, diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index fa391bac1e..d87d5c1d6f 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -2,8 +2,8 @@ use crate::{ handler::mainnet, interpreter::Gas, - primitives::{db::Database, ChainSpec, EVMResultGeneric, ResultAndState, Spec}, - Context, FrameResult, + primitives::{db::Database, EVMResultGeneric, ResultAndState, Spec}, + ChainSpec, Context, FrameResult, }; use std::sync::Arc; diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 40527752c0..38b0d746ef 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -1,8 +1,8 @@ // Includes. use crate::{ handler::mainnet, - primitives::{db::Database, ChainSpec, EVMResultGeneric, Spec}, - Context, ContextPrecompiles, + primitives::{db::Database, EVMResultGeneric, Spec}, + ChainSpec, Context, ContextPrecompiles, }; use std::sync::Arc; diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index df00f724b0..a69be9508c 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -1,10 +1,9 @@ use crate::{ handler::mainnet, primitives::{ - db::Database, ChainSpec, EVMResultGeneric, Env, InvalidTransaction, Spec, - TransactionValidation, + db::Database, EVMResultGeneric, Env, InvalidTransaction, Spec, TransactionValidation, }, - Context, + ChainSpec, Context, }; use std::sync::Arc; diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 649c02fcd3..462e843ba1 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -5,8 +5,8 @@ use crate::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, SharedMemory, }, - primitives::{ChainSpec, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction}, - CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, + primitives::{EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction}, + CallFrame, ChainSpec, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use core::mem; use revm_interpreter::{ diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index 871a06f666..ee2f16e56f 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,10 +1,10 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, Block, Bytecode, ChainSpec, EVMError, EVMResultGeneric, ExecutionResult, - ResultAndState, Spec, SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, + db::Database, Block, Bytecode, EVMError, EVMResultGeneric, ExecutionResult, ResultAndState, + Spec, SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, }, - Context, FrameResult, + ChainSpec, Context, FrameResult, }; /// Mainnet end handle does not change the output. diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 827f8d38dd..610248a85f 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -5,10 +5,10 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ - db::Database, Account, Block, ChainSpec, EVMError, EVMResultGeneric, Env, Spec, SpecId, + db::Database, Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction as _, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, - Context, ContextPrecompiles, + ChainSpec, Context, ContextPrecompiles, }; use std::vec::Vec; diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index 1b50e4fe0a..eb4bbc4ec1 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -2,10 +2,10 @@ use revm_interpreter::gas; use crate::{ primitives::{ - db::Database, ChainSpec, EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, - Transaction, TransactionValidation, + db::Database, EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, Transaction, + TransactionValidation, }, - Context, + ChainSpec, Context, }; /// Validate environment for the mainnet. diff --git a/crates/revm/src/handler/register.rs b/crates/revm/src/handler/register.rs index ba1b30620c..be300ca999 100644 --- a/crates/revm/src/handler/register.rs +++ b/crates/revm/src/handler/register.rs @@ -1,4 +1,4 @@ -use crate::{db::Database, handler::Handler, primitives::ChainSpec, Context}; +use crate::{db::Database, handler::Handler, ChainSpec, Context}; use std::boxed::Box; /// EVM Handler diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 23635ddfb5..55096076a0 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -12,8 +12,8 @@ use crate::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, }, - primitives::{db::Database, Address, ChainSpec, Log, U256}, - EvmContext, + primitives::{db::Database, Address, Log, U256}, + ChainSpec, EvmContext, }; use auto_impl::auto_impl; diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index faa104062b..a23501ffdc 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -8,8 +8,8 @@ use revm_interpreter::OpCode; use crate::{ inspectors::GasInspector, interpreter::{CallInputs, CreateInputs, Interpreter}, - primitives::{Address, ChainSpec, U256}, - Database, EvmContext, Inspector, + primitives::{Address, U256}, + ChainSpec, Database, EvmContext, Inspector, }; /// Custom print [Inspector], it has step level information of execution. diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 6d22653280..ba531c3ce0 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -3,8 +3,8 @@ use crate::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterResult, }, - primitives::{db::Database, hex, ChainSpec, HashMap, Transaction, B256, U256}, - EvmContext, Inspector, + primitives::{db::Database, hex, HashMap, Transaction, B256, U256}, + ChainSpec, EvmContext, Inspector, }; use revm_interpreter::OpCode; use serde::Serialize; diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index ee9a4f377f..dfa5a5c1d0 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -4,8 +4,8 @@ use revm_interpreter::CallOutcome; use crate::{ interpreter::{CallInputs, CreateInputs, CreateOutcome}, - primitives::{db::Database, ChainSpec}, - EvmContext, Inspector, + primitives::db::Database, + ChainSpec, EvmContext, Inspector, }; /// Helper [Inspector] that keeps track of gas. @@ -84,12 +84,12 @@ impl Inspector for GasInspe mod tests { use super::*; - use crate::{interpreter::Interpreter, primitives::Log}; + use crate::{ + interpreter::Interpreter, + primitives::{self, Log}, + }; - #[cfg(feature = "optimism")] - type TestChainSpec = crate::optimism::OptimismChainSpec; - #[cfg(not(feature = "optimism"))] - type TestChainSpec = crate::primitives::EthChainSpec; + type TestChainSpec = primitives::EthChainSpec; #[derive(Default, Debug)] struct StackInspector { @@ -195,22 +195,11 @@ mod tests { .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { - *tx = ::Transaction::default(); - - #[cfg(feature = "optimism")] - let (caller, transact_to, gas_limit) = ( - &mut tx.base.caller, - &mut tx.base.transact_to, - &mut tx.base.gas_limit, - ); - - #[cfg(not(feature = "optimism"))] - let (caller, transact_to, gas_limit) = - (&mut tx.caller, &mut tx.transact_to, &mut tx.gas_limit); - - *caller = address!("1000000000000000000000000000000000000000"); - *transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); - *gas_limit = 21100; + *tx = ::Transaction::default(); + + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); + tx.gas_limit = 21100; }) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 07c8ce9bc2..1729bb6aa0 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -2,8 +2,8 @@ use crate::{ db::Database, handler::register::EvmHandler, interpreter::{opcode, InstructionResult, Interpreter}, - primitives::{ChainSpec, EVMResultGeneric}, - Context, FrameOrResult, FrameResult, Inspector, JournalEntry, + primitives::EVMResultGeneric, + ChainSpec, Context, FrameOrResult, FrameResult, Inspector, JournalEntry, }; use core::cell::RefCell; use revm_interpreter::opcode::DynInstruction; @@ -262,13 +262,10 @@ mod tests { use crate::{ inspectors::NoOpInspector, interpreter::{CallInputs, CallOutcome, CreateInputs, CreateOutcome}, - Evm, EvmContext, + primitives, Evm, EvmContext, }; - #[cfg(feature = "optimism")] - type TestChainSpec = crate::optimism::OptimismChainSpec; - #[cfg(not(feature = "optimism"))] - type TestChainSpec = crate::primitives::EthChainSpec; + type TestChainSpec = primitives::EthChainSpec; #[derive(Default, Debug)] struct StackInspector { @@ -381,22 +378,11 @@ mod tests { .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { - *tx = ::Transaction::default(); - - #[cfg(feature = "optimism")] - let (caller, transact_to, gas_limit) = ( - &mut tx.base.caller, - &mut tx.base.transact_to, - &mut tx.base.gas_limit, - ); - - #[cfg(not(feature = "optimism"))] - let (caller, transact_to, gas_limit) = - (&mut tx.caller, &mut tx.transact_to, &mut tx.gas_limit); - - *caller = address!("1000000000000000000000000000000000000000"); - *transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); - *gas_limit = 21100; + *tx = ::Transaction::default(); + + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); + tx.gas_limit = 21100; }) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/revm/src/inspector/noop.rs b/crates/revm/src/inspector/noop.rs index fe0c295683..412356178c 100644 --- a/crates/revm/src/inspector/noop.rs +++ b/crates/revm/src/inspector/noop.rs @@ -1,4 +1,5 @@ -use crate::{primitives::ChainSpec, Database, Inspector}; +use crate::{ChainSpec, Database, Inspector}; + /// Dummy [Inspector], helpful as standalone replacement. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoOpInspector; diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index cb42740d71..1896be4eb5 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -14,6 +14,7 @@ mod context; #[cfg(any(test, feature = "test-utils"))] pub mod test_utils; +mod chain_spec; pub mod db; mod evm; mod frame; @@ -26,6 +27,7 @@ pub mod optimism; // Export items. pub use builder::EvmBuilder; +pub use chain_spec::ChainSpec; pub use context::{ Context, ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index b3bca67bbe..e80ae2f8bb 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -2,13 +2,11 @@ mod env; mod fast_lz; -mod handler; mod handler_register; mod l1block; mod result; mod spec; -pub use env::OptimismBlock; pub use handler_register::{ deduct_caller, end, last_frame_return, load_precompiles, optimism_handle_register, output, reward_beneficiary, validate_env, validate_tx_against_state, diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index 6d478be534..4ed242acf5 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -1,85 +1,9 @@ -use crate::{ - primitives::{ - db::Database, AccessListItem, Address, AuthorizationList, BlobExcessGasAndPrice, Block, - BlockEnv, Bytes, Transaction, TransactionValidation, TxEnv, TxKind, B256, U256, - }, - L1BlockInfo, +use crate::primitives::{ + AccessListItem, Address, AuthorizationList, Bytes, Transaction, TransactionValidation, TxEnv, + TxKind, B256, U256, }; -use super::{OptimismInvalidTransaction, OptimismSpecId}; - -/// The Optimism block environment. -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct OptimismBlock { - pub base: BlockEnv, - /// L1 block info used to compute the L1-cost fee. - /// - /// Needs to be provided for Optimism non-deposit transactions. - l1_block_info: Option, -} - -impl OptimismBlock { - /// Constructs a new instance. - pub fn new(base: BlockEnv, l1_block_info: Option) -> Self { - Self { - base, - l1_block_info, - } - } - - /// Create a new Optimism block environment. - pub fn with_l1_block_info( - base: BlockEnv, - db: &mut DB, - spec_id: OptimismSpecId, - ) -> Result { - let l1_block_info = L1BlockInfo::try_fetch(db, spec_id)?; - - Ok(Self { - base, - l1_block_info: Some(l1_block_info), - }) - } - - /// Retrieves the L1 block info. - pub fn l1_block_info(&self) -> Option<&L1BlockInfo> { - self.l1_block_info.as_ref() - } -} - -impl Block for OptimismBlock { - fn number(&self) -> &U256 { - self.base.number() - } - - fn coinbase(&self) -> &Address { - self.base.coinbase() - } - - fn timestamp(&self) -> &U256 { - self.base.timestamp() - } - - fn gas_limit(&self) -> &U256 { - self.base.gas_limit() - } - - fn basefee(&self) -> &U256 { - self.base.basefee() - } - - fn difficulty(&self) -> &U256 { - self.base.difficulty() - } - - fn prevrandao(&self) -> Option<&B256> { - self.base.prevrandao() - } - - fn blob_excess_gas_and_price(&self) -> Option<&BlobExcessGasAndPrice> { - self.base.blob_excess_gas_and_price() - } -} +use super::OptimismInvalidTransaction; /// The Optimism transaction environment. #[derive(Clone, Debug, Default, PartialEq, Eq)] diff --git a/crates/revm/src/optimism/handler.rs b/crates/revm/src/optimism/handler.rs deleted file mode 100644 index 1002b429c6..0000000000 --- a/crates/revm/src/optimism/handler.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{ - handler::register::{EvmHandler, HandleRegisters}, - primitives::db::Database, -}; - -use super::OptimismChainSpec; - -impl EvmHandler<'_, OptimismChainSpec, EXT, DB> { - /// Optimism with spec. Similar to [`Self::mainnet_with_spec`]. - pub fn optimism_with_spec(spec_id: crate::optimism::OptimismSpecId) -> Self { - let mut handler = Self::mainnet_with_spec(spec_id); - - handler.append_handler_register(HandleRegisters::Plain( - crate::optimism::optimism_handle_register::, - )); - - handler - } -} diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index bd67baf5e9..971b3f85e5 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -8,8 +8,8 @@ use crate::{ interpreter::{return_ok, return_revert, Gas, InstructionResult}, optimism, optimism_spec_to_generic, primitives::{ - db::Database, Account, Block, EVMError, Env, ExecutionResult, HashMap, InvalidTransaction, - ResultAndState, Transaction, U256, + db::Database, Account, Block, EVMError, EVMResultGeneric, Env, ExecutionResult, HashMap, + InvalidTransaction, ResultAndState, Transaction, U256, }, Context, ContextPrecompiles, FrameResult, }; @@ -33,8 +33,7 @@ pub fn optimism_handle_register( // Load additional precompiles for the given chain spec. handler.pre_execution.load_precompiles = Arc::new(load_precompiles::); // load l1 data - handler.pre_execution.load_accounts = - Arc::new(mainnet::load_accounts::); + handler.pre_execution.load_accounts = Arc::new(load_accounts::); // An estimated batch cost is charged from the caller and added to L1 Fee Vault. handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); // Refund is calculated differently then mainnet. @@ -52,20 +51,12 @@ pub fn validate_env( ) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. if env.tx.source_hash.is_some() { - if env.block.l1_block_info().is_some() { - return Err(OptimismInvalidTransaction::UnexpectedL1BlockInfo.into()); - } else { - return Ok(()); - } + return Ok(()); } // Important: validate block before tx. env.validate_block_env::()?; - if env.block.l1_block_info().is_none() { - return Err(OptimismInvalidTransaction::MissingL1BlockInfo.into()); - } - // Do not allow for a system transaction to be processed if Regolith is enabled. if env.tx.is_system_transaction.unwrap_or(false) && SPEC::optimism_enabled(OptimismSpecId::REGOLITH) @@ -75,6 +66,7 @@ pub fn validate_env( env.validate_tx::() .map_err(OptimismInvalidTransaction::Base)?; + Ok(()) } @@ -176,6 +168,25 @@ pub fn load_precompiles( precompiles } +/// Load account (make them warm) and l1 data from database. +#[inline] +fn load_accounts( + context: &mut Context, +) -> EVMResultGeneric<(), OptimismChainSpec, DB::Error> { + // the L1-cost fee is only computed for Optimism non-deposit transactions. + + if context.evm.env.tx.source_hash.is_none() { + let l1_block_info = + super::L1BlockInfo::try_fetch(&mut context.evm.inner.db, SPEC::OPTIMISM_SPEC_ID) + .map_err(EVMError::Database)?; + + // storage l1 block info for later use. + context.evm.chain.l1_block_info = Some(l1_block_info); + } + + mainnet::load_accounts::(context) +} + /// Deduct max balance from caller #[inline] pub fn deduct_caller( @@ -215,10 +226,9 @@ pub fn deduct_caller( let tx_l1_cost = context .evm - .inner - .env - .block - .l1_block_info() + .chain + .l1_block_info + .as_ref() .expect("L1BlockInfo should be loaded") .calculate_tx_l1_cost(enveloped_tx, SPEC::OPTIMISM_SPEC_ID); if tx_l1_cost.gt(&caller_account.info.balance) { @@ -253,10 +263,9 @@ pub fn reward_beneficiary( // to both the Base Fee Vault as well as the L1 Fee Vault. let l1_block_info = context .evm - .inner - .env - .block - .l1_block_info() + .chain + .l1_block_info + .as_ref() .expect("L1BlockInfo should be loaded"); let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx else { @@ -391,8 +400,8 @@ mod tests { use super::*; use crate::{ db::{EmptyDB, InMemoryDB}, - optimism::{env::OptimismBlock, BedrockSpec, LatestSpec, RegolithSpec}, - primitives::{bytes, state::AccountInfo, Address, BlockEnv, Bytes, Env, B256}, + optimism::{BedrockSpec, LatestSpec, RegolithSpec}, + primitives::{bytes, state::AccountInfo, Address, Bytes, Env, B256}, L1BlockInfo, }; @@ -488,15 +497,12 @@ mod tests { ); let mut context: Context = Context::new_with_db(db); - context.evm.inner.env.block = OptimismBlock::new( - BlockEnv::default(), - Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..L1BlockInfo::default() - }), - ); + context.evm.chain.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); // Enveloped needs to be some but it will deduce zero fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("")); // added mint value is 10. @@ -526,15 +532,12 @@ mod tests { }, ); let mut context: Context = Context::new_with_db(db); - context.evm.inner.env.block = OptimismBlock::new( - BlockEnv::default(), - Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..L1BlockInfo::default() - }), - ); + context.evm.chain.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); // l1block cost is 1048 fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); // added mint value is 10. @@ -567,15 +570,12 @@ mod tests { }, ); let mut context: Context = Context::new_with_db(db); - context.evm.inner.env.block = OptimismBlock::new( - BlockEnv::default(), - Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..L1BlockInfo::default() - }), - ); + context.evm.chain.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); // l1block cost is 1048 fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); deduct_caller::(&mut context).unwrap(); @@ -602,15 +602,12 @@ mod tests { }, ); let mut context: Context = Context::new_with_db(db); - context.evm.inner.env.block = OptimismBlock::new( - BlockEnv::default(), - Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..L1BlockInfo::default() - }), - ); + context.evm.chain.l1_block_info = Some(L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_fee_overhead: Some(U256::from(1_000)), + l1_base_fee_scalar: U256::from(1_000), + ..Default::default() + }); // l1block cost is 1048 fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); @@ -629,18 +626,7 @@ mod tests { #[test] fn test_validate_sys_tx() { // mark the tx as a system transaction. - let mut env = Env:: { - block: OptimismBlock::new( - BlockEnv::default(), - Some(L1BlockInfo { - l1_base_fee: U256::from(1_000), - l1_fee_overhead: Some(U256::from(1_000)), - l1_base_fee_scalar: U256::from(1_000), - ..L1BlockInfo::default() - }), - ), - ..Env::default() - }; + let mut env = Env::::default(); env.tx.is_system_transaction = Some(true); assert_eq!( validate_env::(&env), diff --git a/crates/revm/src/optimism/result.rs b/crates/revm/src/optimism/result.rs index 75bd6b8165..94a0d9ec1b 100644 --- a/crates/revm/src/optimism/result.rs +++ b/crates/revm/src/optimism/result.rs @@ -37,10 +37,6 @@ pub enum OptimismInvalidTransaction { /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this /// case for failed deposit transactions. HaltedDepositPostRegolith, - /// L1 block info is missing for a non-deposit transaction. - MissingL1BlockInfo, - /// L1 block info is provided for a deposit transaction. - UnexpectedL1BlockInfo, } impl Display for OptimismInvalidTransaction { @@ -59,12 +55,6 @@ impl Display for OptimismInvalidTransaction { "deposit transaction halted post-regolith; error will be bubbled up to main return handler" ) } - Self::MissingL1BlockInfo => { - write!(f, "non-deposit transaction is missing L1 block info") - } - Self::UnexpectedL1BlockInfo => { - write!(f, "deposit transaction has unexpected L1 block info") - } } } } diff --git a/crates/revm/src/optimism/spec.rs b/crates/revm/src/optimism/spec.rs index 0bb0c9d267..4eab1b2d80 100644 --- a/crates/revm/src/optimism/spec.rs +++ b/crates/revm/src/optimism/spec.rs @@ -1,22 +1,47 @@ use revm_precompile::PrecompileSpecId; -use crate::primitives::{ChainSpec, Spec, SpecId}; - -use super::{ - env::{OptimismBlock, OptimismTransaction}, - OptimismHaltReason, +use crate::{ + handler::register::HandleRegisters, + primitives::{db::Database, BlockEnv, Spec, SpecId}, + ChainSpec, EvmHandler, L1BlockInfo, }; +use super::{env::OptimismTransaction, OptimismHaltReason}; + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct OptimismChainSpec; -impl ChainSpec for OptimismChainSpec { - type Block = OptimismBlock; +impl crate::primitives::ChainSpec for OptimismChainSpec { + type Block = BlockEnv; type Hardfork = OptimismSpecId; type HaltReason = OptimismHaltReason; type Transaction = OptimismTransaction; } +impl ChainSpec for OptimismChainSpec { + type Context = Context; + + fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> + where + DB: Database, + { + let mut handler = EvmHandler::mainnet_with_spec(hardfork); + + handler.append_handler_register(HandleRegisters::Plain( + crate::optimism::optimism_handle_register::, + )); + + handler + } +} + +/// Context for the Optimism chain. +#[derive(Default)] +pub struct Context { + /// Cached L1 block information. + pub l1_block_info: Option, +} + /// Specification IDs for the optimism blockchain. #[repr(u8)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] From 93089c3a8dbde00a01d9f104c8fe7bab2d3c1894 Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 22 Jul 2024 18:42:26 +0000 Subject: [PATCH 24/59] refactor: generalise optimism implementation using traits --- crates/revm/src/handler.rs | 2 +- crates/revm/src/optimism.rs | 60 ++++++ crates/revm/src/optimism/env.rs | 32 ++- crates/revm/src/optimism/handler_register.rs | 205 ++++++++++--------- crates/revm/src/optimism/spec.rs | 27 ++- 5 files changed, 214 insertions(+), 112 deletions(-) diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 2185fc554b..be44ef16eb 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -199,7 +199,7 @@ mod test { use super::*; #[cfg(feature = "optimism")] - type TestChainSpec = crate::optimism::OptimismChainSpec; + type TestChainSpec = crate::optimism::ChainSpec; #[cfg(not(feature = "optimism"))] type TestChainSpec = primitives::EthChainSpec; diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index e80ae2f8bb..6445ef0683 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -7,6 +7,7 @@ mod l1block; mod result; mod spec; +use crate::primitives::{Bytes, TransactionValidation, B256}; pub use handler_register::{ deduct_caller, end, last_frame_return, load_precompiles, optimism_handle_register, output, reward_beneficiary, validate_env, validate_tx_against_state, @@ -14,3 +15,62 @@ pub use handler_register::{ pub use l1block::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; pub use result::{OptimismHaltReason, OptimismInvalidTransaction}; pub use spec::*; + +pub trait OptimismContext { + /// A reference to the cached L1 block info. + fn l1_block_info(&self) -> Option<&L1BlockInfo>; + + /// A mutable reference to the cached L1 block info. + fn l1_block_info_mut(&mut self) -> &mut Option; +} + +/// Trait for an Optimism transaction. +pub trait OptimismTransaction { + /// The source hash is used to make sure that deposit transactions do + /// not have identical hashes. + /// + /// L1 originated deposit transaction source hashes are computed using + /// the hash of the l1 block hash and the l1 log index. + /// L1 attributes deposit source hashes are computed with the l1 block + /// hash and the sequence number = l2 block number - l2 epoch start + /// block number. + /// + /// These two deposit transaction sources specify a domain in the outer + /// hash so there are no collisions. + fn source_hash(&self) -> Option<&B256>; + /// The amount to increase the balance of the `from` account as part of + /// a deposit transaction. This is unconditional and is applied to the + /// `from` account even if the deposit transaction fails since + /// the deposit is pre-paid on L1. + fn mint(&self) -> Option<&u128>; + /// Whether or not the transaction is a system transaction. + fn is_system_transaction(&self) -> Option; + /// An enveloped EIP-2718 typed transaction. This is used + /// to compute the L1 tx cost using the L1 block info, as + /// opposed to requiring downstream apps to compute the cost + /// externally. + fn enveloped_tx(&self) -> Option; +} + +/// Trait for an Optimism chain spec. +pub trait OptimismChainSpec: + crate::ChainSpec< + Context: OptimismContext, + Hardfork = OptimismSpecId, + HaltReason = OptimismHaltReason, + Transaction: OptimismTransaction + + TransactionValidation, +> +{ +} + +impl OptimismChainSpec for ChainSpecT where + ChainSpecT: crate::ChainSpec< + Context: OptimismContext, + Hardfork = OptimismSpecId, + HaltReason = OptimismHaltReason, + Transaction: OptimismTransaction + + TransactionValidation, + > +{ +} diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index 4ed242acf5..7a155a2a11 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -1,16 +1,16 @@ use crate::primitives::{ - AccessListItem, Address, AuthorizationList, Bytes, Transaction, TransactionValidation, TxEnv, - TxKind, B256, U256, + AccessListItem, Address, AuthorizationList, Bytes, Transaction, TransactionValidation, TxKind, + B256, U256, }; -use super::OptimismInvalidTransaction; +use super::{OptimismInvalidTransaction, OptimismTransaction}; /// The Optimism transaction environment. #[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct OptimismTransaction { +pub struct TxEnv { #[cfg_attr(feature = "serde", serde(flatten))] - pub base: TxEnv, + pub base: crate::primitives::TxEnv, /// The source hash is used to make sure that deposit transactions do /// not have identical hashes. @@ -38,7 +38,7 @@ pub struct OptimismTransaction { pub enveloped_tx: Option, } -impl Transaction for OptimismTransaction { +impl Transaction for TxEnv { fn caller(&self) -> &Address { self.base.caller() } @@ -92,6 +92,24 @@ impl Transaction for OptimismTransaction { } } -impl TransactionValidation for OptimismTransaction { +impl OptimismTransaction for TxEnv { + fn source_hash(&self) -> Option<&B256> { + self.source_hash.as_ref() + } + + fn mint(&self) -> Option<&u128> { + self.mint.as_ref() + } + + fn is_system_transaction(&self) -> Option { + self.is_system_transaction.clone() + } + + fn enveloped_tx(&self) -> Option { + self.enveloped_tx.clone() + } +} + +impl TransactionValidation for TxEnv { type ValidationError = OptimismInvalidTransaction; } diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 971b3f85e5..af5568cad3 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -19,38 +19,46 @@ use std::string::ToString; use std::sync::Arc; use super::{ - OptimismChainSpec, OptimismHaltReason, OptimismInvalidTransaction, OptimismSpec, OptimismSpecId, + OptimismChainSpec, OptimismContext, OptimismHaltReason, OptimismInvalidTransaction, + OptimismSpec, OptimismSpecId, OptimismTransaction as _, }; -pub fn optimism_handle_register( - handler: &mut EvmHandler<'_, OptimismChainSpec, EXT, DB>, -) { +pub fn optimism_handle_register( + handler: &mut EvmHandler<'_, ChainSpecT, EXT, DB>, +) where + ChainSpecT: OptimismChainSpec, + DB: Database, +{ optimism_spec_to_generic!(handler.spec_id, { // validate environment - handler.validation.env = Arc::new(validate_env::); + handler.validation.env = Arc::new(validate_env::); // Validate transaction against state. - handler.validation.tx_against_state = Arc::new(validate_tx_against_state::); + handler.validation.tx_against_state = + Arc::new(validate_tx_against_state::); // Load additional precompiles for the given chain spec. - handler.pre_execution.load_precompiles = Arc::new(load_precompiles::); + handler.pre_execution.load_precompiles = + Arc::new(load_precompiles::); // load l1 data - handler.pre_execution.load_accounts = Arc::new(load_accounts::); + handler.pre_execution.load_accounts = Arc::new(load_accounts::); // An estimated batch cost is charged from the caller and added to L1 Fee Vault. - handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); + handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); // Refund is calculated differently then mainnet. - handler.execution.last_frame_return = Arc::new(last_frame_return::); - handler.post_execution.reward_beneficiary = Arc::new(reward_beneficiary::); + handler.execution.last_frame_return = + Arc::new(last_frame_return::); + handler.post_execution.reward_beneficiary = + Arc::new(reward_beneficiary::); // In case of halt of deposit transaction return Error. - handler.post_execution.output = Arc::new(output::); - handler.post_execution.end = Arc::new(end::); + handler.post_execution.output = Arc::new(output::); + handler.post_execution.end = Arc::new(end::); }); } /// Validate environment for the Optimism chain. -pub fn validate_env( - env: &Env, +pub fn validate_env( + env: &Env, ) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. - if env.tx.source_hash.is_some() { + if env.tx.source_hash().is_some() { return Ok(()); } @@ -58,7 +66,7 @@ pub fn validate_env( env.validate_block_env::()?; // Do not allow for a system transaction to be processed if Regolith is enabled. - if env.tx.is_system_transaction.unwrap_or(false) + if env.tx.is_system_transaction().unwrap_or(false) && SPEC::optimism_enabled(OptimismSpecId::REGOLITH) { return Err(OptimismInvalidTransaction::DepositSystemTxPostRegolith.into()); @@ -71,24 +79,29 @@ pub fn validate_env( } /// Don not perform any extra validation for deposit transactions, they are pre-verified on L1. -pub fn validate_tx_against_state( - context: &mut Context, +pub fn validate_tx_against_state< + ChainSpecT: OptimismChainSpec, + SPEC: OptimismSpec, + EXT, + DB: Database, +>( + context: &mut Context, ) -> Result<(), EVMError> { - if context.evm.inner.env.tx.source_hash.is_some() { + if context.evm.inner.env.tx.source_hash().is_some() { return Ok(()); } - mainnet::validate_tx_against_state::(context) + mainnet::validate_tx_against_state::(context) } /// Handle output of the transaction #[inline] -pub fn last_frame_return( - context: &mut Context, +pub fn last_frame_return( + context: &mut Context, frame_result: &mut FrameResult, ) -> Result<(), EVMError> { let env = context.evm.inner.env(); - let is_deposit = env.tx.source_hash.is_some(); - let tx_system = env.tx.is_system_transaction; + let is_deposit = env.tx.source_hash().is_some(); + let tx_system = env.tx.is_system_transaction(); let tx_gas_limit = env.tx.gas_limit(); let is_regolith = SPEC::optimism_enabled(OptimismSpecId::REGOLITH); @@ -154,8 +167,8 @@ pub fn last_frame_return( /// Load precompiles for Optimism chain. #[inline] -pub fn load_precompiles( -) -> ContextPrecompiles { +pub fn load_precompiles( +) -> ContextPrecompiles { let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)); if SPEC::optimism_enabled(OptimismSpecId::FJORD) { @@ -170,27 +183,27 @@ pub fn load_precompiles( /// Load account (make them warm) and l1 data from database. #[inline] -fn load_accounts( - context: &mut Context, -) -> EVMResultGeneric<(), OptimismChainSpec, DB::Error> { +fn load_accounts( + context: &mut Context, +) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { // the L1-cost fee is only computed for Optimism non-deposit transactions. - if context.evm.env.tx.source_hash.is_none() { + if context.evm.env.tx.source_hash().is_none() { let l1_block_info = super::L1BlockInfo::try_fetch(&mut context.evm.inner.db, SPEC::OPTIMISM_SPEC_ID) .map_err(EVMError::Database)?; // storage l1 block info for later use. - context.evm.chain.l1_block_info = Some(l1_block_info); + *context.evm.chain.l1_block_info_mut() = Some(l1_block_info); } - mainnet::load_accounts::(context) + mainnet::load_accounts::(context) } /// Deduct max balance from caller #[inline] -pub fn deduct_caller( - context: &mut Context, +pub fn deduct_caller( + context: &mut Context, ) -> Result<(), EVMError> { // load caller's account. let (caller_account, _) = context @@ -206,19 +219,19 @@ pub fn deduct_caller( // If the transaction is a deposit with a `mint` value, add the mint value // in wei to the caller's balance. This should be persisted to the database // prior to the rest of execution. - if let Some(mint) = context.evm.inner.env.tx.mint { - caller_account.info.balance += U256::from(mint); + if let Some(mint) = context.evm.inner.env.tx.mint() { + caller_account.info.balance += U256::from(*mint); } // We deduct caller max balance after minting and before deducing the // l1 cost, max values is already checked in pre_validate but l1 cost wasn't. - deduct_caller_inner::(caller_account, &context.evm.inner.env); + deduct_caller_inner::(caller_account, &context.evm.inner.env); // If the transaction is not a deposit transaction, subtract the L1 data fee from the // caller's balance directly after minting the requested amount of ETH. - if context.evm.inner.env.tx.source_hash.is_none() { + if context.evm.inner.env.tx.source_hash().is_none() { // get envelope - let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx else { + let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx() else { return Err(EVMError::Custom( "[OPTIMISM] Failed to load enveloped transaction.".to_string(), )); @@ -227,8 +240,7 @@ pub fn deduct_caller( let tx_l1_cost = context .evm .chain - .l1_block_info - .as_ref() + .l1_block_info() .expect("L1BlockInfo should be loaded") .calculate_tx_l1_cost(enveloped_tx, SPEC::OPTIMISM_SPEC_ID); if tx_l1_cost.gt(&caller_account.info.balance) { @@ -247,15 +259,15 @@ pub fn deduct_caller( /// Reward beneficiary with gas fee. #[inline] -pub fn reward_beneficiary( - context: &mut Context, +pub fn reward_beneficiary( + context: &mut Context, gas: &Gas, ) -> Result<(), EVMError> { - let is_deposit = context.evm.inner.env.tx.source_hash.is_some(); + let is_deposit = context.evm.inner.env.tx.source_hash().is_some(); // transfer fee to coinbase/beneficiary. if !is_deposit { - mainnet::reward_beneficiary::(context, gas)?; + mainnet::reward_beneficiary::(context, gas)?; } if !is_deposit { @@ -264,11 +276,10 @@ pub fn reward_beneficiary( let l1_block_info = context .evm .chain - .l1_block_info - .as_ref() + .l1_block_info() .expect("L1BlockInfo should be loaded"); - let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx else { + let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx() else { return Err(EVMError::Custom( "[OPTIMISM] Failed to load enveloped transaction.".to_string(), )); @@ -307,17 +318,17 @@ pub fn reward_beneficiary( /// Main return handle, returns the output of the transaction. #[inline] -pub fn output( - context: &mut Context, +pub fn output( + context: &mut Context, frame_result: FrameResult, -) -> Result, EVMError> { - let result = mainnet::output::(context, frame_result)?; +) -> Result, EVMError> { + let result = mainnet::output::(context, frame_result)?; if result.result.is_halt() { // Post-regolith, if the transaction is a deposit transaction and it halts, // we bubble up to the global return handler. The mint value will be persisted // and the caller nonce will be incremented there. - let is_deposit = context.evm.inner.env.tx.source_hash.is_some(); + let is_deposit = context.evm.inner.env.tx.source_hash().is_some(); if is_deposit && SPEC::optimism_enabled(OptimismSpecId::REGOLITH) { return Err(EVMError::Transaction( OptimismInvalidTransaction::HaltedDepositPostRegolith, @@ -329,16 +340,13 @@ pub fn output( /// Optimism end handle changes output if the transaction is a deposit transaction. /// Deposit transaction can't be reverted and is always successful. #[inline] -pub fn end( - context: &mut Context, - evm_output: Result< - ResultAndState, - EVMError, - >, -) -> Result, EVMError> { +pub fn end( + context: &mut Context, + evm_output: Result, EVMError>, +) -> Result, EVMError> { evm_output.or_else(|err| { if matches!(err, EVMError::Transaction(_)) - && context.evm.inner.env().tx.source_hash.is_some() + && context.evm.inner.env().tx.source_hash().is_some() { // If the transaction is a deposit transaction and it failed // for any reason, the caller nonce must be bumped, and the @@ -360,10 +368,9 @@ pub fn end( .unwrap_or_default(), ); acc.info.nonce = acc.info.nonce.saturating_add(1); - acc.info.balance = acc - .info - .balance - .saturating_add(U256::from(context.evm.inner.env().tx.mint.unwrap_or(0))); + acc.info.balance = acc.info.balance.saturating_add(U256::from( + context.evm.inner.env().tx.mint().cloned().unwrap_or(0), + )); acc.mark_touch(); acc }; @@ -373,7 +380,12 @@ pub fn end( // limit of the transaction. pre-regolith, it is the gas limit // of the transaction for non system transactions and 0 for system // transactions. - let is_system_tx = context.evm.env().tx.is_system_transaction.unwrap_or(false); + let is_system_tx = context + .evm + .env() + .tx + .is_system_transaction() + .unwrap_or(false); let gas_used = if SPEC::optimism_enabled(OptimismSpecId::REGOLITH) || !is_system_tx { context.evm.inner.env().tx.gas_limit() } else { @@ -400,17 +412,20 @@ mod tests { use super::*; use crate::{ db::{EmptyDB, InMemoryDB}, - optimism::{BedrockSpec, LatestSpec, RegolithSpec}, + optimism::{self, BedrockSpec, LatestSpec, RegolithSpec}, primitives::{bytes, state::AccountInfo, Address, Bytes, Env, B256}, L1BlockInfo, }; /// Creates frame result. - fn call_last_frame_return( - env: Env, + fn call_last_frame_return( + env: Env, instruction_result: InstructionResult, gas: Gas, - ) -> Gas { + ) -> Gas + where + SPEC: OptimismSpec, + { let mut ctx = Context::new_empty(); ctx.evm.inner.env = Box::new(env); let mut first_frame = FrameResult::Call(CallOutcome::new( @@ -421,13 +436,13 @@ mod tests { }, 0..0, )); - last_frame_return::(&mut ctx, &mut first_frame).unwrap(); + last_frame_return::(&mut ctx, &mut first_frame).unwrap(); *first_frame.gas() } #[test] fn test_revert_gas() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = None; @@ -440,7 +455,7 @@ mod tests { #[test] fn test_consume_gas() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -453,7 +468,7 @@ mod tests { #[test] fn test_consume_gas_with_refund() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -474,7 +489,7 @@ mod tests { #[test] fn test_consume_gas_sys_deposit_tx() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -496,8 +511,8 @@ mod tests { }, ); - let mut context: Context = Context::new_with_db(db); - context.evm.chain.l1_block_info = Some(L1BlockInfo { + let mut context: Context = Context::new_with_db(db); + *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), l1_base_fee_scalar: U256::from(1_000), @@ -508,7 +523,7 @@ mod tests { // added mint value is 10. context.evm.inner.env.tx.mint = Some(10); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let (account, _) = context @@ -531,8 +546,8 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); - context.evm.chain.l1_block_info = Some(L1BlockInfo { + let mut context: Context = Context::new_with_db(db); + *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), l1_base_fee_scalar: U256::from(1_000), @@ -546,7 +561,7 @@ mod tests { // so enveloped_tx gas cost is ignored. context.evm.inner.env.tx.source_hash = Some(B256::ZERO); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let (account, _) = context @@ -569,8 +584,8 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); - context.evm.chain.l1_block_info = Some(L1BlockInfo { + let mut context: Context = Context::new_with_db(db); + *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), l1_base_fee_scalar: U256::from(1_000), @@ -578,7 +593,7 @@ mod tests { }); // l1block cost is 1048 fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let (account, _) = context @@ -601,8 +616,8 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); - context.evm.chain.l1_block_info = Some(L1BlockInfo { + let mut context: Context = Context::new_with_db(db); + *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), l1_base_fee_scalar: U256::from(1_000), @@ -612,7 +627,7 @@ mod tests { context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); assert_eq!( - deduct_caller::(&mut context), + deduct_caller::(&mut context), Err(EVMError::Transaction( InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(U256::from(1048)), @@ -626,34 +641,34 @@ mod tests { #[test] fn test_validate_sys_tx() { // mark the tx as a system transaction. - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.is_system_transaction = Some(true); assert_eq!( - validate_env::(&env), + validate_env::(&env), Err(EVMError::Transaction( OptimismInvalidTransaction::DepositSystemTxPostRegolith )) ); // Pre-regolith system transactions should be allowed. - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_deposit_tx() { // Set source hash. - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.source_hash = Some(B256::ZERO); - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_tx_against_state_deposit_tx() { // Set source hash. - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.source_hash = Some(B256::ZERO); // Nonce and balance checks should be skipped for deposit transactions. - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } } diff --git a/crates/revm/src/optimism/spec.rs b/crates/revm/src/optimism/spec.rs index 4eab1b2d80..4698ec37f9 100644 --- a/crates/revm/src/optimism/spec.rs +++ b/crates/revm/src/optimism/spec.rs @@ -3,22 +3,22 @@ use revm_precompile::PrecompileSpecId; use crate::{ handler::register::HandleRegisters, primitives::{db::Database, BlockEnv, Spec, SpecId}, - ChainSpec, EvmHandler, L1BlockInfo, + EvmHandler, L1BlockInfo, }; -use super::{env::OptimismTransaction, OptimismHaltReason}; +use super::{env::TxEnv, OptimismContext, OptimismHaltReason}; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct OptimismChainSpec; +pub struct ChainSpec; -impl crate::primitives::ChainSpec for OptimismChainSpec { +impl crate::primitives::ChainSpec for ChainSpec { type Block = BlockEnv; type Hardfork = OptimismSpecId; type HaltReason = OptimismHaltReason; - type Transaction = OptimismTransaction; + type Transaction = TxEnv; } -impl ChainSpec for OptimismChainSpec { +impl crate::ChainSpec for ChainSpec { type Context = Context; fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> @@ -28,7 +28,7 @@ impl ChainSpec for OptimismChainSpec { let mut handler = EvmHandler::mainnet_with_spec(hardfork); handler.append_handler_register(HandleRegisters::Plain( - crate::optimism::optimism_handle_register::, + crate::optimism::optimism_handle_register::, )); handler @@ -38,8 +38,17 @@ impl ChainSpec for OptimismChainSpec { /// Context for the Optimism chain. #[derive(Default)] pub struct Context { - /// Cached L1 block information. - pub l1_block_info: Option, + l1_block_info: Option, +} + +impl OptimismContext for Context { + fn l1_block_info(&self) -> Option<&L1BlockInfo> { + self.l1_block_info.as_ref() + } + + fn l1_block_info_mut(&mut self) -> &mut Option { + &mut self.l1_block_info + } } /// Specification IDs for the optimism blockchain. From da8175a27a2cc126ab91ce394c650c07ab15e130 Mon Sep 17 00:00:00 2001 From: Wodann Date: Tue, 23 Jul 2024 17:33:56 +0000 Subject: [PATCH 25/59] fix: no-default-features --- crates/revm/src/chain_spec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index e063d07827..589ccac2c0 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -4,6 +4,7 @@ use crate::{ primitives::{db::Database, spec_to_generic, EthChainSpec}, EvmHandler, }; +use std::vec::Vec; pub trait ChainSpec: crate::primitives::ChainSpec { /// The type that contains all context information for the chain's EVM execution. From 0f052b5bdbd68eb1fac91fbf7bfe479c9823024f Mon Sep 17 00:00:00 2001 From: Wodann Date: Mon, 29 Jul 2024 19:14:19 +0000 Subject: [PATCH 26/59] fix: CI --- bins/revme/src/cmd/statetest/runner.rs | 3 -- crates/primitives/src/result.rs | 55 -------------------------- crates/revm/src/optimism/env.rs | 2 +- 3 files changed, 1 insertion(+), 59 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index f61e359ee0..6ecd0da8af 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -28,9 +28,6 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; -#[cfg(feature = "optimism")] -type TestChainSpec = revm::optimism::OptimismChainSpec; -#[cfg(not(feature = "optimism"))] type TestChainSpec = revm::primitives::EthChainSpec; #[derive(Debug, Error)] diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index f3de017438..cf6e608c48 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -223,45 +223,6 @@ impl From } } -/// Transaction validation error for Optimism. -#[cfg(feature = "optimism")] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum OptimismInvalidTransaction { - /// System transactions are not supported post-regolith hardfork. - /// - /// Before the Regolith hardfork, there was a special field in the `Deposit` transaction - /// type that differentiated between `system` and `user` deposit transactions. This field - /// was deprecated in the Regolith hardfork, and this error is thrown if a `Deposit` transaction - /// is found with this field set to `true` after the hardfork activation. - /// - /// In addition, this error is internal, and bubbles up into a [HaltReason::FailedDeposit] error - /// in the `revm` handler for the consumer to easily handle. This is due to a state transition - /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction - /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and - /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors - /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this - /// case for failed deposit transactions. - #[cfg(feature = "optimism")] - DepositSystemTxPostRegolith, - /// Deposit transaction haults bubble up to the global main return handler, wiping state and - /// only increasing the nonce + persisting the mint value. - /// - /// This is a catch-all error for any deposit transaction that is results in a [HaltReason] error - /// post-regolith hardfork. This allows for a consumer to easily handle special cases where - /// a deposit transaction fails during validation, but must still be included in the block. - /// - /// In addition, this error is internal, and bubbles up into a [HaltReason::FailedDeposit] error - /// in the `revm` handler for the consumer to easily handle. This is due to a state transition - /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction - /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and - /// special gas accounting rules are applied. Normally on L1, [EVMError::Transaction] errors - /// are cause for non-inclusion, so a special [HaltReason] variant was introduced to handle this - /// case for failed deposit transactions. - #[cfg(feature = "optimism")] - HaltedDepositPostRegolith, -} - /// Transaction validation error. #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -336,22 +297,6 @@ pub enum InvalidTransaction { #[cfg(feature = "std")] impl std::error::Error for InvalidTransaction {} -#[cfg(feature = "optimism")] -impl fmt::Display for OptimismInvalidTransaction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::DepositSystemTxPostRegolith => write!( - f, - "deposit system transactions post regolith hardfork are not supported" - ), - Self::HaltedDepositPostRegolith => write!( - f, - "deposit transaction halted post-regolith; error will be bubbled up to main return handler" - ), - } - } -} - impl fmt::Display for InvalidTransaction { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/crates/revm/src/optimism/env.rs b/crates/revm/src/optimism/env.rs index 7a155a2a11..32863938aa 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/revm/src/optimism/env.rs @@ -102,7 +102,7 @@ impl OptimismTransaction for TxEnv { } fn is_system_transaction(&self) -> Option { - self.is_system_transaction.clone() + self.is_system_transaction } fn enveloped_tx(&self) -> Option { From 69e73040f74811683819bf8167c1e7927b0a3ba3 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 12:53:38 +0200 Subject: [PATCH 27/59] chore: Add default fn to Tx/Block traits --- .../interpreter/src/instructions/host_env.rs | 6 ++-- crates/primitives/src/block.rs | 34 +++++++++---------- crates/primitives/src/env.rs | 17 ++++------ crates/primitives/src/lib.rs | 6 ++-- crates/primitives/src/transaction.rs | 13 ++++--- 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/crates/interpreter/src/instructions/host_env.rs b/crates/interpreter/src/instructions/host_env.rs index 2ffb25e34c..fa95533e4f 100644 --- a/crates/interpreter/src/instructions/host_env.rs +++ b/crates/interpreter/src/instructions/host_env.rs @@ -1,6 +1,6 @@ use crate::{ gas, - primitives::{block, Block, Spec, SpecId::*, Transaction, U256}, + primitives::{Block, Spec, SpecId::*, Transaction, U256}, Host, Interpreter, }; @@ -76,7 +76,9 @@ pub fn blob_basefee(interpreter: &mut Interpreter, push!( interpreter, U256::from( - block::get_blob_gasprice(&host.env().block) + host.env() + .block + .get_blob_gasprice() .copied() .unwrap_or_default() ) diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 1a5003acb4..38056c110b 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -43,24 +43,22 @@ pub trait Block { /// /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 fn blob_excess_gas_and_price(&self) -> Option<&BlobExcessGasAndPrice>; -} -/// See [EIP-4844] and [`crate::calc_blob_gasprice`]. -/// -/// Returns `None` if `Cancun` is not enabled. This is enforced in [`crate::Env::validate_block_env`]. -/// -/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 -#[inline] -pub fn get_blob_gasprice(block: &impl Block) -> Option<&u128> { - block.blob_excess_gas_and_price().map(|a| &a.blob_gasprice) -} + /// See [EIP-4844] and [`crate::calc_blob_gasprice`]. + /// + /// Returns `None` if `Cancun` is not enabled. This is enforced in [`crate::Env::validate_block_env`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + fn get_blob_gasprice(&self) -> Option<&u128> { + self.blob_excess_gas_and_price().map(|a| &a.blob_gasprice) + } -/// Return `blob_excess_gas` header field. See [EIP-4844]. -/// -/// Returns `None` if `Cancun` is not enabled. This is enforced in [`crate::Env::validate_block_env`]. -/// -/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 -#[inline] -pub fn get_blob_excess_gas(block: &impl Block) -> Option { - block.blob_excess_gas_and_price().map(|a| a.excess_blob_gas) + /// Return `blob_excess_gas` header field. See [EIP-4844]. + /// + /// Returns `None` if `Cancun` is not enabled. This is enforced in [`crate::Env::validate_block_env`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + fn get_blob_excess_gas(&self) -> Option { + self.blob_excess_gas_and_price().map(|a| a.excess_blob_gas) + } } diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index c73707a8d6..4bbe7eed93 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -5,10 +5,9 @@ pub use eip7702::{ }; use crate::{ - block, calc_blob_gasprice, transaction, AccessListItem, Account, Address, Block, Bytes, - ChainSpec, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, - B256, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, - VERSIONED_HASH_VERSION_KZG, + calc_blob_gasprice, AccessListItem, Account, Address, Block, Bytes, ChainSpec, InvalidHeader, + InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, B256, KECCAK_EMPTY, + MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, }; use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; @@ -55,9 +54,8 @@ impl Env { /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 #[inline] pub fn calc_data_fee(&self) -> Option { - block::get_blob_gasprice(&self.block).map(|blob_gas_price| { - U256::from(*blob_gas_price) - .saturating_mul(U256::from(transaction::get_total_blob_gas(&self.tx))) + self.block.get_blob_gasprice().map(|blob_gas_price| { + U256::from(*blob_gas_price).saturating_mul(U256::from(self.tx.get_total_blob_gas())) }) } @@ -70,8 +68,7 @@ impl Env { /// pub fn calc_max_data_fee(&self) -> Option { self.tx.max_fee_per_blob_gas().map(|max_fee_per_blob_gas| { - max_fee_per_blob_gas - .saturating_mul(U256::from(transaction::get_total_blob_gas(&self.tx))) + max_fee_per_blob_gas.saturating_mul(U256::from(self.tx.get_total_blob_gas())) }) } @@ -152,7 +149,7 @@ impl Env { // Presence of max_fee_per_blob_gas means that this is blob transaction. if let Some(max) = self.tx.max_fee_per_blob_gas() { // ensure that the user was willing to at least pay the current blob gasprice - let price = block::get_blob_gasprice(&self.block).expect("already checked"); + let price = self.block.get_blob_gasprice().expect("already checked"); if U256::from(*price) > *max { return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 681ac101dd..ae0582f45f 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -7,13 +7,13 @@ #[cfg(not(feature = "std"))] extern crate alloc as std; -mod bytecode; -mod constants; +pub mod block; pub mod db; pub mod env; -pub mod block; +mod bytecode; mod chain_spec; +mod constants; #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg; pub mod precompile; diff --git a/crates/primitives/src/transaction.rs b/crates/primitives/src/transaction.rs index 28452dfc74..f2a1577f70 100644 --- a/crates/primitives/src/transaction.rs +++ b/crates/primitives/src/transaction.rs @@ -54,12 +54,11 @@ pub trait Transaction { /// /// [EIP-Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) fn authorization_list(&self) -> Option<&AuthorizationList>; -} -/// See [EIP-4844], [`crate::Env::calc_data_fee`], and [`crate::Env::calc_max_data_fee`]. -/// -/// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 -#[inline] -pub fn get_total_blob_gas(transaction: &impl Transaction) -> u64 { - GAS_PER_BLOB * transaction.blob_hashes().len() as u64 + /// See [EIP-4844], [`crate::Env::calc_data_fee`], and [`crate::Env::calc_max_data_fee`]. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + fn get_total_blob_gas(&self) -> u64 { + GAS_PER_BLOB * self.blob_hashes().len() as u64 + } } From 946d404fb74faf57662dafa82c919e6a4d4b26d8 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 13:01:37 +0200 Subject: [PATCH 28/59] Chore: rename ChainSpec to EvmWiring --- bins/revme/src/cmd/statetest/runner.rs | 8 +- crates/interpreter/src/gas/calc.rs | 2 +- crates/interpreter/src/host.rs | 14 +- crates/interpreter/src/host/dummy.rs | 26 +-- crates/interpreter/src/instruction_result.rs | 14 +- .../interpreter/src/instructions/bitwise.rs | 10 +- .../interpreter/src/instructions/control.rs | 18 +- crates/interpreter/src/instructions/data.rs | 6 +- crates/interpreter/src/instructions/stack.rs | 8 +- crates/interpreter/src/instructions/system.rs | 6 +- crates/interpreter/src/interpreter.rs | 16 +- .../interpreter/src/interpreter/contract.rs | 6 +- .../interpreter_action/eof_create_inputs.rs | 4 +- crates/primitives/src/chain_spec.rs | 6 +- crates/primitives/src/env.rs | 22 +- crates/primitives/src/result.rs | 26 +-- crates/revm/benches/bench.rs | 8 +- crates/revm/src/builder.rs | 206 +++++++++--------- crates/revm/src/chain_spec.rs | 6 +- crates/revm/src/context.rs | 48 ++-- .../revm/src/context/context_precompiles.rs | 62 +++--- crates/revm/src/context/evm_context.rs | 72 +++--- crates/revm/src/context/inner_evm_context.rs | 22 +- crates/revm/src/custom_upcode.rs | 12 +- crates/revm/src/db/states/state.rs | 2 +- crates/revm/src/evm.rs | 72 +++--- crates/revm/src/handler.rs | 78 +++---- crates/revm/src/handler/cfg.rs | 50 ++--- .../src/handler/handle_types/execution.rs | 162 +++++++------- .../handler/handle_types/post_execution.rs | 76 +++---- .../src/handler/handle_types/pre_execution.rs | 48 ++-- .../src/handler/handle_types/validation.rs | 48 ++-- crates/revm/src/handler/mainnet/execution.rs | 82 +++---- .../src/handler/mainnet/post_execution.rs | 32 +-- .../revm/src/handler/mainnet/pre_execution.rs | 24 +- crates/revm/src/handler/mainnet/validation.rs | 26 +-- crates/revm/src/handler/register.rs | 24 +- crates/revm/src/inspector.rs | 24 +- crates/revm/src/inspector/customprinter.rs | 18 +- crates/revm/src/inspector/eip3155.rs | 18 +- crates/revm/src/inspector/gas.rs | 38 ++-- crates/revm/src/inspector/handler_register.rs | 52 ++--- crates/revm/src/inspector/noop.rs | 4 +- crates/revm/src/lib.rs | 4 +- crates/revm/src/optimism.rs | 8 +- crates/revm/src/optimism/handler_register.rs | 122 +++++------ crates/revm/src/optimism/spec.rs | 6 +- examples/db_by_ref.rs | 8 +- 48 files changed, 827 insertions(+), 827 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 6ecd0da8af..f1d5fbccc3 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -28,7 +28,7 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; -type TestChainSpec = revm::primitives::EthChainSpec; +type TestEvmWiring = revm::primitives::EthEvmWiring; #[derive(Debug, Error)] #[error("Test {name} failed: {kind}")] @@ -132,8 +132,8 @@ fn check_evm_execution( test: &Test, expected_output: Option<&Bytes>, test_name: &str, - exec_result: &EVMResultGeneric, TestChainSpec, Infallible>, - evm: &Evm<'_, TestChainSpec, EXT, &mut State>, + exec_result: &EVMResultGeneric, TestEvmWiring, Infallible>, + evm: &Evm<'_, TestEvmWiring, EXT, &mut State>, print_json_outcome: bool, ) -> Result<(), TestError> { let logs_root = log_rlp_hash(exec_result.as_ref().map(|r| r.logs()).unwrap_or_default()); @@ -270,7 +270,7 @@ pub fn execute_test_suite( cache_state.insert_account_with_storage(address, acc_info, info.storage); } - let mut env = Box::>::default(); + let mut env = Box::>::default(); // for mainnet env.cfg.chain_id = 1; // env.cfg.spec_id is set down the road diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 5e33c43fbf..2895bd28a5 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -287,7 +287,7 @@ pub const fn selfdestruct_cost(spec_id: SpecId, res: SelfDestructResult) -> u64 /// * Account access gas. after berlin it can be cold or warm. /// * Transfer value gas. If value is transferred and balance of target account is updated. /// * If account is not existing and needs to be created. After Spurious dragon -/// this is only accounted if value is transferred. +/// this is only accounted if value is transferred. #[inline] pub const fn call_cost( spec_id: SpecId, diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 4dc65b5172..c9563a826a 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -2,18 +2,18 @@ use crate::primitives::{Address, Bytes, Env, Log, B256, U256}; mod dummy; pub use dummy::DummyHost; -use revm_primitives::ChainSpec; +use revm_primitives::EvmWiring; /// EVM context host. pub trait Host { /// Chain specification. - type ChainSpecT: ChainSpec; + type EvmWiringT: EvmWiring; /// Returns a reference to the environment. - fn env(&self) -> &Env; + fn env(&self) -> &Env; /// Returns a mutable reference to the environment. - fn env_mut(&mut self) -> &mut Env; + fn env_mut(&mut self) -> &mut Env; /// Load an account. /// @@ -88,7 +88,7 @@ pub struct SelfDestructResult { #[cfg(test)] mod tests { - use revm_primitives::EthChainSpec; + use revm_primitives::EthEvmWiring; use super::*; @@ -96,7 +96,7 @@ mod tests { #[test] fn object_safety() { - assert_host::>(); - assert_host::>(); + assert_host::>(); + assert_host::>(); } } diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index c398f1a932..f2e816cb64 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -2,7 +2,7 @@ use derive_where::derive_where; use crate::{ primitives::{ - hash_map::Entry, Address, Bytes, ChainSpec, Env, HashMap, Log, B256, KECCAK_EMPTY, U256, + hash_map::Entry, Address, Bytes, Env, EvmWiring, HashMap, Log, B256, KECCAK_EMPTY, U256, }, Host, SStoreResult, SelfDestructResult, }; @@ -11,24 +11,24 @@ use std::vec::Vec; use super::LoadAccountResult; /// A dummy [Host] implementation. -#[derive_where(Clone, Debug, Default; ChainSpecT::Block, ChainSpecT::Transaction)] -pub struct DummyHost +#[derive_where(Clone, Debug, Default; EvmWiringT::Block, EvmWiringT::Transaction)] +pub struct DummyHost where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { - pub env: Env, + pub env: Env, pub storage: HashMap, pub transient_storage: HashMap, pub log: Vec, } -impl DummyHost +impl DummyHost where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { /// Create a new dummy host with the given [`Env`]. #[inline] - pub fn new(env: Env) -> Self { + pub fn new(env: Env) -> Self { Self { env, storage: HashMap::new(), @@ -45,19 +45,19 @@ where } } -impl Host for DummyHost +impl Host for DummyHost where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { - type ChainSpecT = ChainSpecT; + type EvmWiringT = EvmWiringT; #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &Env { &self.env } #[inline] - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut Env { &mut self.env } diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index 910e086685..0fc7eb72aa 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -1,7 +1,7 @@ use core::fmt::Debug; use derive_where::derive_where; -use revm_primitives::ChainSpec; +use revm_primitives::EvmWiring; use crate::primitives::{HaltReason, OutOfGasError, SuccessReason}; @@ -213,16 +213,16 @@ pub enum InternalResult { } #[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[derive_where(Debug; ChainSpecT::HaltReason)] -pub enum SuccessOrHalt { +#[derive_where(Debug; EvmWiringT::HaltReason)] +pub enum SuccessOrHalt { Success(SuccessReason), Revert, - Halt(ChainSpecT::HaltReason), + Halt(EvmWiringT::HaltReason), FatalExternalError, Internal(InternalResult), } -impl SuccessOrHalt { +impl SuccessOrHalt { /// Returns true if the transaction returned successfully without halts. #[inline] pub fn is_success(self) -> bool { @@ -252,7 +252,7 @@ impl SuccessOrHalt { /// Returns the [HaltReason] value the EVM has experienced an exceptional halt #[inline] - pub fn to_halt(self) -> Option { + pub fn to_halt(self) -> Option { match self { SuccessOrHalt::Halt(reason) => Some(reason), _ => None, @@ -260,7 +260,7 @@ impl SuccessOrHalt { } } -impl From for SuccessOrHalt { +impl From for SuccessOrHalt { fn from(result: InstructionResult) -> Self { match result { InstructionResult::Continue => Self::Internal(InternalResult::InternalContinue), // used only in interpreter loop diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 068db1bccb..d156c3ce33 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -125,7 +125,7 @@ pub fn sar(interpreter: &mut Interpreter, _host: & mod tests { use crate::instructions::bitwise::{byte, sar, shl, shr}; use crate::{Contract, DummyHost, Interpreter}; - use revm_primitives::{uint, Env, EthChainSpec, LatestSpec, U256}; + use revm_primitives::{uint, Env, EthEvmWiring, LatestSpec, U256}; #[test] fn test_shift_left() { @@ -202,7 +202,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shl::, LatestSpec>(&mut interpreter, &mut host); + shl::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -283,7 +283,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shr::, LatestSpec>(&mut interpreter, &mut host); + shr::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -389,7 +389,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - sar::, LatestSpec>(&mut interpreter, &mut host); + sar::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -403,7 +403,7 @@ mod tests { expected: U256, } - let mut host = DummyHost::new(Env::::default()); + let mut host = DummyHost::new(Env::::default()); let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index f625dd8c3a..a9e081d871 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -206,7 +206,7 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { mod test { use std::sync::Arc; - use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, EthChainSpec, PragueSpec}; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, EthEvmWiring, PragueSpec}; use super::*; use crate::{ @@ -216,7 +216,7 @@ mod test { #[test] fn rjump() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMP, 0x00, 0x02, STOP, STOP, @@ -230,7 +230,7 @@ mod test { #[test] fn rjumpi() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP, @@ -250,7 +250,7 @@ mod test { #[test] fn rjumpv() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPV, @@ -332,7 +332,7 @@ mod test { #[test] fn callf_retf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]); let bytes2 = Bytes::from([RETF]); @@ -363,7 +363,7 @@ mod test { #[test] fn callf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -387,7 +387,7 @@ mod test { #[test] fn callf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -404,7 +404,7 @@ mod test { #[test] fn jumpf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -425,7 +425,7 @@ mod test { #[test] fn jumpf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index 6fd5dfcf9b..99f031c8b1 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -83,7 +83,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { - use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, EthChainSpec, PragueSpec}; + use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, EthEvmWiring, PragueSpec}; use std::sync::Arc; use super::*; @@ -107,7 +107,7 @@ mod test { #[test] fn dataload_dataloadn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([ DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN, @@ -163,7 +163,7 @@ mod test { #[test] fn data_copy() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY])); diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index f39c0fb6c1..dde28b61ee 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -89,13 +89,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, DUPN, EXCHANGE, SWAPN}, - primitives::{Bytecode, Bytes, EthChainSpec, PragueSpec}, + primitives::{Bytecode, Bytes, EthEvmWiring, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn dupn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ DUPN, 0x00, DUPN, 0x01, DUPN, 0x02, @@ -115,7 +115,7 @@ mod test { #[test] fn swapn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([SWAPN, 0x00, SWAPN, 0x01]))); @@ -135,7 +135,7 @@ mod test { #[test] fn exchange() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ EXCHANGE, 0x00, EXCHANGE, 0x11, diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 112d9fa156..8d7ac22a3b 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -189,13 +189,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, RETURNDATACOPY, RETURNDATALOAD}, - primitives::{bytes, Bytecode, EthChainSpec, PragueSpec}, + primitives::{bytes, Bytecode, EthEvmWiring, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn returndataload() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( @@ -254,7 +254,7 @@ mod test { #[test] fn returndatacopy() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( [ diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index c4e1598eea..935f62fbe3 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -469,21 +469,21 @@ pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) mod tests { use super::*; use crate::{opcode::InstructionTable, DummyHost}; - use revm_primitives::{CancunSpec, EthChainSpec}; + use revm_primitives::{CancunSpec, EthEvmWiring}; #[test] fn object_safety() { let mut interp = Interpreter::new(Contract::default(), u64::MAX, false); - let mut host = crate::DummyHost::::default(); - let table: &InstructionTable> = - &crate::opcode::make_instruction_table::, CancunSpec>(); + let mut host = crate::DummyHost::::default(); + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::, CancunSpec>(); let _ = interp.run(EMPTY_SHARED_MEMORY, table, &mut host); - let host: &mut dyn Host = - &mut host as &mut dyn Host; - let table: &InstructionTable> = - &crate::opcode::make_instruction_table::, CancunSpec>( + let host: &mut dyn Host = + &mut host as &mut dyn Host; + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::, CancunSpec>( ); let _ = interp.run(EMPTY_SHARED_MEMORY, table, host); } diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 53ca74e3f4..f4e19642d5 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,4 +1,4 @@ -use revm_primitives::ChainSpec; +use revm_primitives::EvmWiring; use super::analysis::to_analysed; use crate::{ @@ -55,8 +55,8 @@ impl Contract { /// Creates a new contract from the given [`Env`]. #[inline] - pub fn new_env( - env: &Env, + pub fn new_env( + env: &Env, bytecode: Bytecode, hash: Option, ) -> Self { diff --git a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs index fd8b63f1dd..5846d66fee 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs @@ -1,4 +1,4 @@ -use revm_primitives::ChainSpec; +use revm_primitives::EvmWiring; use crate::primitives::{Address, Bytes, Eof, Transaction as _, U256}; @@ -75,7 +75,7 @@ impl EOFCreateInputs { } /// Creates new EOFCreateInputs from transaction. - pub fn new_tx(tx: &ChainSpecT::Transaction, gas_limit: u64) -> Self { + pub fn new_tx(tx: &EvmWiringT::Transaction, gas_limit: u64) -> Self { EOFCreateInputs::new( *tx.caller(), *tx.value(), diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 4b383fb944..1387f06f0e 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -32,7 +32,7 @@ pub trait TransactionValidation { } } -pub trait ChainSpec: Sized + 'static { +pub trait EvmWiring: Sized + 'static { /// The type that contains all block information. type Block: Block; @@ -47,9 +47,9 @@ pub trait ChainSpec: Sized + 'static { } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct EthChainSpec; +pub struct EthEvmWiring; -impl ChainSpec for EthChainSpec { +impl EvmWiring for EthEvmWiring { type Block = crate::BlockEnv; type Hardfork = SpecId; type HaltReason = crate::HaltReason; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 4bbe7eed93..736bb51716 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -5,7 +5,7 @@ pub use eip7702::{ }; use crate::{ - calc_blob_gasprice, AccessListItem, Account, Address, Block, Bytes, ChainSpec, InvalidHeader, + calc_blob_gasprice, AccessListItem, Account, Address, Block, Bytes, EvmWiring, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, B256, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, }; @@ -18,21 +18,21 @@ use std::boxed::Box; use std::vec::Vec; /// EVM environment configuration. -#[derive_where(Clone, Debug, Default; ChainSpecT::Block, ChainSpecT::Transaction)] +#[derive_where(Clone, Debug, Default; EvmWiringT::Block, EvmWiringT::Transaction)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Env { +pub struct Env { /// Configuration of the EVM itself. pub cfg: CfgEnv, /// Configuration of the block the transaction is in. - pub block: ChainSpecT::Block, + pub block: EvmWiringT::Block, /// Configuration of the transaction that is being executed. - pub tx: ChainSpecT::Transaction, + pub tx: EvmWiringT::Transaction, } -impl Env { +impl Env { /// Create boxed [Env]. #[inline] - pub fn boxed(cfg: CfgEnv, block: ChainSpecT::Block, tx: ChainSpecT::Transaction) -> Box { + pub fn boxed(cfg: CfgEnv, block: EvmWiringT::Block, tx: EvmWiringT::Transaction) -> Box { Box::new(Self { cfg, block, tx }) } @@ -264,7 +264,7 @@ impl Env { } } -impl> Env { +impl> Env { /// Resets environment to default values. #[inline] pub fn clear(&mut self) { @@ -767,13 +767,13 @@ pub enum AnalysisKind { #[cfg(test)] mod tests { - use crate::EthChainSpec; + use crate::EthEvmWiring; use super::*; #[test] fn test_validate_tx_chain_id() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.chain_id = Some(1); env.cfg.chain_id = 2; assert_eq!( @@ -784,7 +784,7 @@ mod tests { #[test] fn test_validate_tx_access_list() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.access_list = vec![AccessListItem { address: Address::ZERO, storage_keys: vec![], diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index cf6e608c48..89f2eb462c 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,35 +1,35 @@ use derive_where::derive_where; -use crate::{Address, Bytes, ChainSpec, EvmState, Log, TransactionValidation, U256}; +use crate::{Address, Bytes, EvmState, EvmWiring, Log, TransactionValidation, U256}; use core::fmt::{self, Debug}; use std::{boxed::Box, string::String, vec::Vec}; /// Result of EVM execution. -pub type EVMResult = - EVMResultGeneric, ChainSpecT, DBError>; +pub type EVMResult = + EVMResultGeneric, EvmWiringT, DBError>; /// Generic result of EVM execution. Used to represent error and generic output. -pub type EVMResultGeneric = - core::result::Result>; +pub type EVMResultGeneric = + core::result::Result>; /// EVM error type for a specific chain. -pub type EVMErrorForChain = EVMError< +pub type EVMErrorForChain = EVMError< DBError, - <::Transaction as TransactionValidation>::ValidationError, + <::Transaction as TransactionValidation>::ValidationError, >; #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ResultAndState { +pub struct ResultAndState { /// Status of execution - pub result: ExecutionResult, + pub result: ExecutionResult, /// State that got updated pub state: EvmState, } /// Result of a transaction execution. #[derive(Debug, PartialEq, Eq, Hash)] -#[derive_where(Clone; ChainSpecT::HaltReason)] -pub enum ExecutionResult { +#[derive_where(Clone; EvmWiringT::HaltReason)] +pub enum ExecutionResult { /// Returned successfully Success { reason: SuccessReason, @@ -42,13 +42,13 @@ pub enum ExecutionResult { Revert { gas_used: u64, output: Bytes }, /// Reverted for various reasons and spend all gas. Halt { - reason: ChainSpecT::HaltReason, + reason: EvmWiringT::HaltReason, /// Halting will spend all the gas, and will be equal to gas_limit. gas_used: u64, }, } -impl ExecutionResult { +impl ExecutionResult { /// Returns if transaction execution is successful. /// 1 indicates success, 0 indicates revert. /// diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index bdba5206c0..8c42e79433 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -4,7 +4,7 @@ use criterion::{ use revm::{ db::BenchmarkDB, interpreter::{analysis::to_analysed, Contract, DummyHost, Interpreter}, - primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, EthChainSpec, TxKind, U256}, + primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, EthEvmWiring, TxKind, U256}, Evm, }; use revm_interpreter::{opcode::make_instruction_table, SharedMemory, EMPTY_SHARED_MEMORY}; @@ -83,7 +83,7 @@ fn transfer(c: &mut Criterion) { fn bench_transact( g: &mut BenchmarkGroup<'_, WallTime>, - evm: &mut Evm<'_, EthChainSpec, EXT, BenchmarkDB>, + evm: &mut Evm<'_, EthEvmWiring, EXT, BenchmarkDB>, ) { let state = match evm.context.evm.db.0 { Bytecode::LegacyRaw(_) => "raw", @@ -96,7 +96,7 @@ fn bench_transact( fn bench_eval( g: &mut BenchmarkGroup<'_, WallTime>, - evm: &mut Evm<'static, EthChainSpec, (), BenchmarkDB>, + evm: &mut Evm<'static, EthEvmWiring, (), BenchmarkDB>, ) { g.bench_function("eval", |b| { let contract = Contract { @@ -106,7 +106,7 @@ fn bench_eval( }; let mut shared_memory = SharedMemory::new(); let mut host = DummyHost::new(*evm.context.evm.env.clone()); - let instruction_table = make_instruction_table::, BerlinSpec>(); + let instruction_table = make_instruction_table::, BerlinSpec>(); b.iter(move || { // replace memory with empty memory to use it inside interpreter. // Later return memory back. diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 4a5a2e065b..8207a7dfee 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,8 +1,8 @@ use crate::{ db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, - handler::{register, CfgEnvWithChainSpec, EnvWithChainSpec}, - primitives::{self, CfgEnv, Env, EthChainSpec, InvalidTransaction, TransactionValidation}, - ChainSpec, Context, ContextWithChainSpec, Evm, EvmContext, Handler, + handler::{register, CfgEnvWithEvmWiring, EnvWithEvmWiring}, + primitives::{self, CfgEnv, Env, EthEvmWiring, InvalidTransaction, TransactionValidation}, + Context, ContextWithEvmWiring, Evm, EvmContext, EvmWiring, Handler, }; use core::marker::PhantomData; use std::boxed::Box; @@ -10,10 +10,10 @@ use std::boxed::Box; /// Evm Builder allows building or modifying EVM. /// Note that some of the methods that changes underlying structures /// will reset the registered handler to default mainnet. -pub struct EvmBuilder<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> { - context: Context, +pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> { + context: Context, /// Handler that will be used by EVM. It contains handle registers - handler: Handler<'a, ChainSpecT, Context, EXT, DB>, + handler: Handler<'a, EvmWiringT, Context, EXT, DB>, /// Phantom data to mark the stage of the builder. phantom: PhantomData, } @@ -26,28 +26,28 @@ pub struct SetGenericStage; /// Requires the database and external context to be set. pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthChainSpec, (), EmptyDB> { +impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthEvmWiring, (), EmptyDB> { fn default() -> Self { Self { context: Context::default(), - handler: EthChainSpec::handler::<'a, (), EmptyDB>( - ::Hardfork::default(), + handler: EthEvmWiring::handler::<'a, (), EmptyDB>( + ::Hardfork::default(), ), phantom: PhantomData, } } } -impl<'a, ChainSpecT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, DB> where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { - /// Sets the [`ChainSpec`] that will be used by [`Evm`]. - pub fn with_chain_spec( + /// Sets the [`EvmWiring`] that will be used by [`Evm`]. + pub fn with_chain_spec( self, - ) -> EvmBuilder<'a, SetGenericStage, NewChainSpecT, EXT, DB> + ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT, EXT, DB> where - NewChainSpecT: ChainSpec< + NewEvmWiringT: EvmWiring< Block: Default, Transaction: Default + TransactionValidation>, >, @@ -56,25 +56,25 @@ where EvmBuilder { context: Context::new(EvmContext::new(evm.inner.db), external), - handler: NewChainSpecT::handler::<'a, EXT, DB>(NewChainSpecT::Hardfork::default()), + handler: NewEvmWiringT::handler::<'a, EXT, DB>(NewEvmWiringT::Hardfork::default()), phantom: PhantomData, } } } -impl<'a, ChainSpecT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, DB> where - ChainSpecT: - ChainSpec>>, + EvmWiringT: + EvmWiring>>, { /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. - pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, EmptyDB> { + pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, EmptyDB> { EvmBuilder { context: Context::new( self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: ChainSpecT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -82,10 +82,10 @@ where pub fn with_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, ODB> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, ODB> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: ChainSpecT::handler::<'a, EXT, ODB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, EXT, ODB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -93,13 +93,13 @@ where pub fn with_ref_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, WrapDatabaseRef> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { EvmBuilder { context: Context::new( self.context.evm.with_db(WrapDatabaseRef(db)), self.context.external, ), - handler: ChainSpecT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), phantom: PhantomData, } } @@ -108,63 +108,63 @@ where pub fn with_external_context( self, external: OEXT, - ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, OEXT, DB> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, OEXT, DB> { EvmBuilder { context: Context::new(self.context.evm, external), - handler: ChainSpecT::handler::<'a, OEXT, DB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, OEXT, DB>(self.handler.spec_id()), phantom: PhantomData, } } - /// Sets Builder with [`EnvWithChainSpec`]. + /// Sets Builder with [`EnvWithEvmWiring`]. pub fn with_env_with_handler_cfg( mut self, - env_with_handler_cfg: EnvWithChainSpec, - ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { - let EnvWithChainSpec { env, spec_id } = env_with_handler_cfg; + env_with_handler_cfg: EnvWithEvmWiring, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { + let EnvWithEvmWiring { env, spec_id } = env_with_handler_cfg; self.context.evm.env = env; EvmBuilder { context: self.context, - handler: ChainSpecT::handler::<'a, EXT, DB>(spec_id), + handler: EvmWiringT::handler::<'a, EXT, DB>(spec_id), phantom: PhantomData, } } - /// Sets Builder with [`ContextWithChainSpec`]. + /// Sets Builder with [`ContextWithEvmWiring`]. pub fn with_context_with_handler_cfg( self, - context_with_handler_cfg: ContextWithChainSpec, - ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, OEXT, ODB> { + context_with_handler_cfg: ContextWithEvmWiring, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, OEXT, ODB> { EvmBuilder { context: context_with_handler_cfg.context, - handler: ChainSpecT::handler::<'a, OEXT, ODB>(context_with_handler_cfg.spec_id), + handler: EvmWiringT::handler::<'a, OEXT, ODB>(context_with_handler_cfg.spec_id), phantom: PhantomData, } } - /// Sets Builder with [`CfgEnvWithChainSpec`]. + /// Sets Builder with [`CfgEnvWithEvmWiring`]. pub fn with_cfg_env_with_handler_cfg( mut self, - cfg_env_and_spec_id: CfgEnvWithChainSpec, - ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { + cfg_env_and_spec_id: CfgEnvWithEvmWiring, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; EvmBuilder { context: self.context, - handler: ChainSpecT::handler::<'a, EXT, DB>(cfg_env_and_spec_id.spec_id), + handler: EvmWiringT::handler::<'a, EXT, DB>(cfg_env_and_spec_id.spec_id), phantom: PhantomData, } } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> - EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> + EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { /// Creates new builder from Evm, Evm is consumed and all field are moved to Builder. /// It will preserve set handler and context. /// /// Builder is in HandlerStage and both database and external are set. - pub fn new(evm: Evm<'a, ChainSpecT, EXT, DB>) -> Self { + pub fn new(evm: Evm<'a, EvmWiringT, EXT, DB>) -> Self { Self { context: evm.context, handler: evm.handler, @@ -173,21 +173,21 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> where - ChainSpecT: - ChainSpec>>, + EvmWiringT: + EvmWiring>>, { /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. pub fn reset_handler_with_empty_db( self, - ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, EmptyDB> { + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, EmptyDB> { EvmBuilder { context: Context::new( self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: ChainSpecT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -197,10 +197,10 @@ where pub fn reset_handler_with_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, ODB> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, ODB> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: ChainSpecT::handler::<'a, EXT, ODB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, EXT, ODB>(self.handler.spec_id()), phantom: PhantomData, } } @@ -210,13 +210,13 @@ where pub fn reset_handler_with_ref_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, EXT, WrapDatabaseRef> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { EvmBuilder { context: Context::new( self.context.evm.with_db(WrapDatabaseRef(db)), self.context.external, ), - handler: ChainSpecT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), phantom: PhantomData, } } @@ -226,29 +226,29 @@ where pub fn reset_handler_with_external_context( self, external: OEXT, - ) -> EvmBuilder<'a, SetGenericStage, ChainSpecT, OEXT, DB> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, OEXT, DB> { EvmBuilder { context: Context::new(self.context.evm, external), - handler: ChainSpecT::handler::<'a, OEXT, DB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a, OEXT, DB>(self.handler.spec_id()), phantom: PhantomData, } } } -impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> - EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> + EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> { /// This modifies the [EvmBuilder] to make it easy to construct an [`Evm`] with a _specific_ /// handler. /// /// # Example /// ```rust - /// use revm::{EvmBuilder, EvmHandler, db::EmptyDB, primitives::{EthChainSpec, SpecId}}; + /// use revm::{EvmBuilder, EvmHandler, db::EmptyDB, primitives::{EthEvmWiring, SpecId}}; /// use revm_interpreter::primitives::CancunSpec; /// let builder = EvmBuilder::default(); /// /// // get the desired handler - /// let mainnet = EvmHandler::<'_, EthChainSpec, (), EmptyDB>::mainnet_with_spec(SpecId::CANCUN); + /// let mainnet = EvmHandler::<'_, EthEvmWiring, (), EmptyDB>::mainnet_with_spec(SpecId::CANCUN); /// let builder = builder.with_handler(mainnet); /// /// // build the EVM @@ -256,8 +256,8 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> /// ``` pub fn with_handler( self, - handler: Handler<'a, ChainSpecT, Context, EXT, DB>, - ) -> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> { + handler: Handler<'a, EvmWiringT, Context, EXT, DB>, + ) -> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> { EvmBuilder { context: self.context, handler, @@ -266,7 +266,7 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> } /// Builds the [`Evm`]. - pub fn build(self) -> Evm<'a, ChainSpecT, EXT, DB> { + pub fn build(self) -> Evm<'a, EvmWiringT, EXT, DB> { Evm::new(self.context, self.handler) } @@ -276,8 +276,8 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. pub fn append_handler_register( mut self, - handle_register: register::HandleRegister, - ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { + handle_register: register::HandleRegister, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { self.handler .append_handler_register(register::HandleRegisters::Plain(handle_register)); EvmBuilder { @@ -294,8 +294,8 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. pub fn append_handler_register_box( mut self, - handle_register: register::HandleRegisterBox<'a, ChainSpecT, EXT, DB>, - ) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { + handle_register: register::HandleRegisterBox<'a, EvmWiringT, EXT, DB>, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { self.handler .append_handler_register(register::HandleRegisters::Box(handle_register)); EvmBuilder { @@ -319,37 +319,37 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> } /// Allows modification of Evm Environment. - pub fn modify_env(mut self, f: impl FnOnce(&mut Box>)) -> Self { + pub fn modify_env(mut self, f: impl FnOnce(&mut Box>)) -> Self { f(&mut self.context.evm.env); self } /// Sets Evm Environment. - pub fn with_env(mut self, env: Box>) -> Self { + pub fn with_env(mut self, env: Box>) -> Self { self.context.evm.env = env; self } /// Allows modification of Evm's Transaction Environment. - pub fn modify_tx_env(mut self, f: impl FnOnce(&mut ChainSpecT::Transaction)) -> Self { + pub fn modify_tx_env(mut self, f: impl FnOnce(&mut EvmWiringT::Transaction)) -> Self { f(&mut self.context.evm.env.tx); self } /// Sets Evm's Transaction Environment. - pub fn with_tx_env(mut self, tx_env: ChainSpecT::Transaction) -> Self { + pub fn with_tx_env(mut self, tx_env: EvmWiringT::Transaction) -> Self { self.context.evm.env.tx = tx_env; self } /// Allows modification of Evm's Block Environment. - pub fn modify_block_env(mut self, f: impl FnOnce(&mut ChainSpecT::Block)) -> Self { + pub fn modify_block_env(mut self, f: impl FnOnce(&mut EvmWiringT::Block)) -> Self { f(&mut self.context.evm.env.block); self } /// Sets Evm's Block Environment. - pub fn with_block_env(mut self, block_env: ChainSpecT::Block) -> Self { + pub fn with_block_env(mut self, block_env: EvmWiringT::Block) -> Self { self.context.evm.env.block = block_env; self } @@ -361,33 +361,33 @@ impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> } } -impl<'a, BuilderStage, ChainSpecT, EXT, DB> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT, EXT, DB> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Clears Block environment of EVM. pub fn with_clear_block_env(mut self) -> Self { - self.context.evm.env.block = ChainSpecT::Block::default(); + self.context.evm.env.block = EvmWiringT::Block::default(); self } } -impl<'a, BuilderStage, ChainSpecT, EXT, DB> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT, EXT, DB> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Clears Transaction environment of EVM. pub fn with_clear_tx_env(mut self) -> Self { - self.context.evm.env.tx = ChainSpecT::Transaction::default(); + self.context.evm.env.tx = EvmWiringT::Transaction::default(); self } } -impl<'a, BuilderStage, ChainSpecT, EXT, DB> EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT, EXT, DB> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Clears Environment of EVM. @@ -397,11 +397,11 @@ where } } -impl<'a, BuilderStage, ChainSpecT: ChainSpec, EXT, DB: Database> - EvmBuilder<'a, BuilderStage, ChainSpecT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> + EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> where - ChainSpecT: - ChainSpec>>, + EvmWiringT: + EvmWiring>>, { /// Sets specification Id , that will mark the version of EVM. /// It represent the hard fork of ethereum. @@ -410,7 +410,7 @@ where /// /// When changed it will reapply all handle registers, this can be /// expensive operation depending on registers. - pub fn with_spec_id(mut self, spec_id: ChainSpecT::Hardfork) -> Self { + pub fn with_spec_id(mut self, spec_id: EvmWiringT::Hardfork) -> Self { self.handler.modify_spec_id(spec_id); EvmBuilder { context: self.context, @@ -422,7 +422,7 @@ where /// Resets [`Handler`] to default mainnet. pub fn reset_handler(mut self) -> Self { - self.handler = ChainSpecT::handler::<'a, EXT, DB>(self.handler.spec_id()); + self.handler = EvmWiringT::handler::<'a, EXT, DB>(self.handler.spec_id()); self } } @@ -442,7 +442,7 @@ mod test { use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; - type TestChainSpec = crate::primitives::EthChainSpec; + type TestEvmWiring = crate::primitives::EthEvmWiring; /// Custom evm context #[derive(Default, Clone, Debug)] @@ -462,7 +462,7 @@ mod test { let to_capture = custom_context.clone(); let mut evm = Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_db(InMemoryDB::default()) .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) @@ -480,7 +480,7 @@ mod test { // we need to use a box to capture the custom context in the instruction let custom_instruction = Box::new( move |_interp: &mut Interpreter, - _host: &mut Context| { + _host: &mut Context| { // modify the value let mut inner = custom_context.inner.borrow_mut(); *inner += 1; @@ -517,7 +517,7 @@ mod test { let to_addr = address!("ffffffffffffffffffffffffffffffffffffffff"); let mut evm = Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_db(InMemoryDB::default()) .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) @@ -539,25 +539,25 @@ mod test { #[test] fn simple_build() { // build without external with latest spec - Evm::builder().with_chain_spec::().build(); + Evm::builder().with_chain_spec::().build(); // build with empty db Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .build(); // build with_db Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_db(EmptyDB::default()) .build(); // build with empty external Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .build(); // build with some external Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .with_external_context(()) .build(); @@ -569,28 +569,28 @@ mod test { // with with Env change in multiple places Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .modify_tx_env(|tx| tx.gas_limit = 10) .build(); Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .modify_tx_env(|tx| tx.gas_limit = 10) .build(); Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .modify_tx_env(|tx| tx.gas_limit = 10) .build(); Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .modify_tx_env(|tx| tx.gas_limit = 10) .build(); // with inspector handle Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_empty_db() .with_external_context(NoOpInspector) .append_handler_register(inspector_handle_register) @@ -599,7 +599,7 @@ mod test { // create the builder let evm = Evm::builder() .with_db(EmptyDB::default()) - .with_chain_spec::() + .with_chain_spec::() .with_external_context(NoOpInspector) .append_handler_register(inspector_handle_register) // this would not compile @@ -629,12 +629,12 @@ mod test { fn build_custom_precompile() { struct CustomPrecompile; - impl ContextStatefulPrecompile for CustomPrecompile { + impl ContextStatefulPrecompile for CustomPrecompile { fn call( &self, _input: &Bytes, _gas_limit: u64, - _context: &mut InnerEvmContext, + _context: &mut InnerEvmContext, ) -> PrecompileResult { Ok(PrecompileOutput::new(10, Bytes::new())) } @@ -643,7 +643,7 @@ mod test { let spec_id = crate::primitives::SpecId::HOMESTEAD; let mut evm = Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_spec_id(spec_id) .append_handler_register(|handler| { let precompiles = handler.pre_execution.load_precompiles(); diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index 589ccac2c0..d079bb1990 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -1,12 +1,12 @@ use crate::{ handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, interpreter::opcode::InstructionTables, - primitives::{db::Database, spec_to_generic, EthChainSpec}, + primitives::{db::Database, spec_to_generic, EthEvmWiring}, EvmHandler, }; use std::vec::Vec; -pub trait ChainSpec: crate::primitives::ChainSpec { +pub trait EvmWiring: crate::primitives::EvmWiring { /// The type that contains all context information for the chain's EVM execution. type Context: Default; @@ -16,7 +16,7 @@ pub trait ChainSpec: crate::primitives::ChainSpec { DB: Database; } -impl ChainSpec for EthChainSpec { +impl EvmWiring for EthEvmWiring { type Context = (); fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 9b007c780f..88f7320f9a 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -15,33 +15,33 @@ use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, primitives::{ - Address, Block as _, Bytes, Env, EthChainSpec, Log, B256, BLOCK_HASH_HISTORY, U256, + Address, Block as _, Bytes, Env, EthEvmWiring, Log, B256, BLOCK_HASH_HISTORY, U256, }, - ChainSpec, + EvmWiring, }; use std::boxed::Box; /// Main Context structure that contains both EvmContext and External context. -#[derive_where(Clone; ChainSpecT::Block, ChainSpecT::Context, ChainSpecT::Transaction, DB, DB::Error, EXT)] -pub struct Context { +#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::Context, EvmWiringT::Transaction, DB, DB::Error, EXT)] +pub struct Context { /// Evm Context (internal context). - pub evm: EvmContext, + pub evm: EvmContext, /// External contexts. pub external: EXT, } -impl Default for Context { +impl Default for Context { fn default() -> Self { Self::new_empty() } } -impl Context +impl Context where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { /// Creates empty context. This is useful for testing. - pub fn new_empty() -> Context { + pub fn new_empty() -> Context { Context { evm: EvmContext::new(EmptyDB::new()), external: (), @@ -49,13 +49,13 @@ where } } -impl Context +impl Context where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Creates new context with database. - pub fn new_with_db(db: DB) -> Context { + pub fn new_with_db(db: DB) -> Context { Context { evm: EvmContext::new_with_env(db, Box::default()), external: (), @@ -63,39 +63,39 @@ where } } -impl Context { +impl Context { /// Creates new context with external and database. - pub fn new(evm: EvmContext, external: EXT) -> Context { + pub fn new(evm: EvmContext, external: EXT) -> Context { Context { evm, external } } } /// Context with handler configuration. -#[derive_where(Clone; ChainSpecT::Block, ChainSpecT::Context, ChainSpecT::Transaction, DB, DB::Error, EXT)] -pub struct ContextWithChainSpec { +#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::Context, EvmWiringT::Transaction, DB, DB::Error, EXT)] +pub struct ContextWithEvmWiring { /// Context of execution. - pub context: Context, + pub context: Context, /// Handler configuration. - pub spec_id: ChainSpecT::Hardfork, + pub spec_id: EvmWiringT::Hardfork, } -impl ContextWithChainSpec { +impl ContextWithEvmWiring { /// Creates new context with handler configuration. - pub fn new(context: Context, spec_id: ChainSpecT::Hardfork) -> Self { + pub fn new(context: Context, spec_id: EvmWiringT::Hardfork) -> Self { Self { spec_id, context } } } -impl Host for Context { - type ChainSpecT = ChainSpecT; +impl Host for Context { + type EvmWiringT = EvmWiringT; /// Returns reference to Environment. #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &Env { &self.evm.env } - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut Env { &mut self.evm.env } diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index 6e68ca6744..6ecee9b8e8 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -1,7 +1,7 @@ use super::InnerEvmContext; use crate::{ precompile::{Precompile, PrecompileResult}, - primitives::{db::Database, Address, Bytes, ChainSpec, HashMap, HashSet}, + primitives::{db::Database, Address, Bytes, EvmWiring, HashMap, HashSet}, }; use core::fmt::Debug; use derive_where::derive_where; @@ -11,18 +11,18 @@ use std::{boxed::Box, sync::Arc}; /// A single precompile handler. #[derive_where(Clone)] -pub enum ContextPrecompile { +pub enum ContextPrecompile { /// Ordinary precompiles Ordinary(Precompile), /// Stateful precompile that is Arc over [`ContextStatefulPrecompile`] trait. /// It takes a reference to input, gas limit and Context. - ContextStateful(ContextStatefulPrecompileArc), + ContextStateful(ContextStatefulPrecompileArc), /// Mutable stateful precompile that is Box over [`ContextStatefulPrecompileMut`] trait. /// It takes a reference to input, gas limit and context. - ContextStatefulMut(ContextStatefulPrecompileBox), + ContextStatefulMut(ContextStatefulPrecompileBox), } -impl Debug for ContextPrecompile { +impl Debug for ContextPrecompile { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::Ordinary(arg0) => f.debug_tuple("Ordinary").field(arg0).finish(), @@ -33,20 +33,20 @@ impl Debug for ContextPrecompile { +enum PrecompilesCow { /// Default precompiles, returned by `Precompiles::new`. Used to fast-path the default case. StaticRef(&'static Precompiles), - Owned(HashMap>), + Owned(HashMap>), } /// Precompiles context. #[derive_where(Clone, Debug, Default)] -pub struct ContextPrecompiles { - inner: PrecompilesCow, +pub struct ContextPrecompiles { + inner: PrecompilesCow, } -impl ContextPrecompiles { +impl ContextPrecompiles { /// Creates a new precompiles context at the given spec ID. /// /// This is a cheap operation that does not allocate by reusing the global precompiles. @@ -69,7 +69,7 @@ impl ContextPrecompiles { /// Creates a new precompiles context from the given precompiles. #[inline] pub fn from_precompiles( - precompiles: HashMap>, + precompiles: HashMap>, ) -> Self { Self { inner: PrecompilesCow::Owned(precompiles), @@ -111,7 +111,7 @@ impl ContextPrecompiles { address: &Address, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> Option { Some(match self.inner { PrecompilesCow::StaticRef(p) => { @@ -129,7 +129,7 @@ impl ContextPrecompiles { /// /// Clones the precompiles map if it is shared. #[inline] - pub fn to_mut(&mut self) -> &mut HashMap> { + pub fn to_mut(&mut self) -> &mut HashMap> { if let PrecompilesCow::StaticRef(_) = self.inner { self.mutate_into_owned(); } @@ -157,10 +157,10 @@ impl ContextPrecompiles { } } -impl Extend<(Address, ContextPrecompile)> - for ContextPrecompiles +impl Extend<(Address, ContextPrecompile)> + for ContextPrecompiles { - fn extend)>>( + fn extend)>>( &mut self, iter: T, ) { @@ -168,8 +168,8 @@ impl Extend<(Address, ContextPrecompile Extend - for ContextPrecompiles +impl Extend + for ContextPrecompiles { fn extend>(&mut self, iter: T) { self.to_mut().extend(iter.into_iter().map(|precompile| { @@ -179,7 +179,7 @@ impl Extend } } -impl Default for PrecompilesCow { +impl Default for PrecompilesCow { fn default() -> Self { Self::Owned(Default::default()) } @@ -187,39 +187,39 @@ impl Default for PrecompilesCow: Sync + Send { +pub trait ContextStatefulPrecompile: Sync + Send { fn call( &self, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> PrecompileResult; } /// Context aware mutable stateful precompile trait. It is used to create /// a boxed precompile in [`ContextPrecompile`]. -pub trait ContextStatefulPrecompileMut: +pub trait ContextStatefulPrecompileMut: DynClone + Send + Sync { fn call_mut( &mut self, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> PrecompileResult; } -dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); +dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); /// Arc over context stateful precompile. -pub type ContextStatefulPrecompileArc = - Arc>; +pub type ContextStatefulPrecompileArc = + Arc>; /// Box over context mutable stateful precompile -pub type ContextStatefulPrecompileBox = - Box>; +pub type ContextStatefulPrecompileBox = + Box>; -impl From for ContextPrecompile { +impl From for ContextPrecompile { fn from(p: Precompile) -> Self { ContextPrecompile::Ordinary(p) } @@ -228,14 +228,14 @@ impl From for ContextPrecompile #[cfg(test)] mod tests { use super::*; - use crate::{db::EmptyDB, primitives::EthChainSpec}; + use crate::{db::EmptyDB, primitives::EthEvmWiring}; #[test] fn test_precompiles_context() { let custom_address = Address::with_last_byte(0xff); let mut precompiles = - ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); + ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); assert_eq!(precompiles.addresses().count(), 4); assert!(matches!(precompiles.inner, PrecompilesCow::StaticRef(_))); assert!(!precompiles.contains(&custom_address)); diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 51024b0f50..bde0e7cc10 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -14,61 +14,61 @@ use crate::{ SpecId::{self, *}, Transaction as _, B256, EOF_MAGIC_BYTES, }, - ChainSpec, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, + ContextPrecompiles, EvmWiring, FrameOrResult, CALL_STACK_LIMIT, }; use core::ops::{Deref, DerefMut}; use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. -#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Context, ChainSpecT::Transaction, DB, DB::Error)] -pub struct EvmContext { +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Context, EvmWiringT::Transaction, DB, DB::Error)] +pub struct EvmContext { /// The context that's unique to the chain type. - pub chain: ChainSpecT::Context, + pub chain: EvmWiringT::Context, /// Inner EVM context. - pub inner: InnerEvmContext, + pub inner: InnerEvmContext, /// Precompiles that are available for evm. - pub precompiles: ContextPrecompiles, + pub precompiles: ContextPrecompiles, } -impl Deref for EvmContext { - type Target = InnerEvmContext; +impl Deref for EvmContext { + type Target = InnerEvmContext; fn deref(&self) -> &Self::Target { &self.inner } } -impl DerefMut for EvmContext { +impl DerefMut for EvmContext { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -impl EvmContext +impl EvmContext where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Create new context with database. pub fn new(db: DB) -> Self { Self { - chain: ChainSpecT::Context::default(), + chain: EvmWiringT::Context::default(), inner: InnerEvmContext::new(db), precompiles: ContextPrecompiles::default(), } } } -impl EvmContext +impl EvmContext where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: DB, env: Box>) -> Self { + pub fn new_with_env(db: DB, env: Box>) -> Self { Self { - chain: ChainSpecT::Context::default(), + chain: EvmWiringT::Context::default(), inner: InnerEvmContext::new_with_env(db, env), precompiles: ContextPrecompiles::default(), } @@ -78,7 +78,7 @@ where /// /// Note that this will ignore the previous `error` if set. #[inline] - pub fn with_db(self, db: ODB) -> EvmContext { + pub fn with_db(self, db: ODB) -> EvmContext { EvmContext { chain: self.chain, inner: self.inner.with_db(db), @@ -88,7 +88,7 @@ where /// Sets precompiles #[inline] - pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { + pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { // set warm loaded addresses. self.journaled_state .warm_preloaded_addresses @@ -103,7 +103,7 @@ where address: &Address, input_data: &Bytes, gas: Gas, - ) -> EVMResultGeneric, ChainSpecT, DB::Error> { + ) -> EVMResultGeneric, EvmWiringT, DB::Error> { let Some(outcome) = self.precompiles .call(address, input_data, gas.limit(), &mut self.inner) @@ -143,7 +143,7 @@ where pub fn make_call_frame( &mut self, inputs: &CallInputs, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -479,11 +479,11 @@ pub(crate) mod test_utils { /// Creates an evm context with a cache db backend. /// Additionally loads the mock caller account into the db, /// and sets the balance to the provided U256 value. - pub fn create_cache_db_evm_context_with_balance( - env: Box>, + pub fn create_cache_db_evm_context_with_balance( + env: Box>, mut db: CacheDB, balance: U256, - ) -> EvmContext> { + ) -> EvmContext> { db.insert_account_info( test_utils::MOCK_CALLER, crate::primitives::AccountInfo { @@ -497,12 +497,12 @@ pub(crate) mod test_utils { } /// Creates a cached db evm context. - pub fn create_cache_db_evm_context( - env: Box>, + pub fn create_cache_db_evm_context( + env: Box>, db: CacheDB, - ) -> EvmContext> { + ) -> EvmContext> { EvmContext { - chain: ChainSpecT::Context::default(), + chain: EvmWiringT::Context::default(), inner: InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), @@ -515,12 +515,12 @@ pub(crate) mod test_utils { } /// Returns a new `EvmContext` with an empty journaled state. - pub fn create_empty_evm_context( - env: Box>, + pub fn create_empty_evm_context( + env: Box>, db: EmptyDB, - ) -> EvmContext { + ) -> EvmContext { EvmContext { - chain: ChainSpecT::Context::default(), + chain: EvmWiringT::Context::default(), inner: InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), @@ -539,7 +539,7 @@ mod tests { use crate::primitives::U256; use crate::{ db::{CacheDB, EmptyDB}, - primitives::{address, Bytecode, EthChainSpec}, + primitives::{address, Bytecode, EthEvmWiring}, Frame, JournalEntry, }; use std::boxed::Box; @@ -549,7 +549,7 @@ mod tests { // call stack is too deep. #[test] fn test_make_call_frame_stack_too_deep() { - let env = Env::::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut context = test_utils::create_empty_evm_context(Box::new(env), db); context.journaled_state.depth = CALL_STACK_LIMIT as usize + 1; @@ -570,7 +570,7 @@ mod tests { // checkpointed on the journaled state correctly. #[test] fn test_make_call_frame_transfer_revert() { - let env = Env::::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut evm_context = test_utils::create_empty_evm_context(Box::new(env), db); let contract = address!("dead10000000000000000000000000000001dead"); @@ -591,7 +591,7 @@ mod tests { #[test] fn test_make_call_frame_missing_code_context() { - let env = Env::::default(); + let env = Env::::default(); let cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let mut context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); @@ -606,7 +606,7 @@ mod tests { #[test] fn test_make_call_frame_succeeds() { - let env = Env::::default(); + let env = Env::::default(); let mut cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let by = Bytecode::new_raw(Bytes::from(vec![0x60, 0x00, 0x60, 0x00])); diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 8d502abfc3..f263518ac6 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -8,8 +8,8 @@ use crate::{ }, journaled_state::JournaledState, primitives::{ - AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, ChainSpec, Env, - Eof, HashSet, Spec, + AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, Env, Eof, + EvmWiring, HashSet, Spec, SpecId::{self, *}, Transaction as _, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, @@ -18,11 +18,11 @@ use crate::{ use std::{boxed::Box, sync::Arc, vec::Vec}; /// EVM contexts contains data that EVM needs for execution. -#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Transaction, DB, DB::Error)] -pub struct InnerEvmContext { +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Transaction, DB, DB::Error)] +pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. - pub env: Box>, + pub env: Box>, /// EVM State with journaling support. pub journaled_state: JournaledState, /// Database to load data from. @@ -33,9 +33,9 @@ pub struct InnerEvmContext { pub valid_authorizations: Vec
, } -impl InnerEvmContext +impl InnerEvmContext where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { pub fn new(db: DB) -> Self { @@ -49,10 +49,10 @@ where } } -impl InnerEvmContext { +impl InnerEvmContext { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: DB, env: Box>) -> Self { + pub fn new_with_env(db: DB, env: Box>) -> Self { Self { env, journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), @@ -66,7 +66,7 @@ impl InnerEvmContext { /// /// Note that this will ignore the previous `error` if set. #[inline] - pub fn with_db(self, db: ODB) -> InnerEvmContext { + pub fn with_db(self, db: ODB) -> InnerEvmContext { InnerEvmContext { env: self.env, journaled_state: self.journaled_state, @@ -103,7 +103,7 @@ impl InnerEvmContext { /// Return environment. #[inline] - pub fn env(&mut self) -> &mut Env { + pub fn env(&mut self) -> &mut Env { &mut self.env } diff --git a/crates/revm/src/custom_upcode.rs b/crates/revm/src/custom_upcode.rs index 4cdb5b2d43..1c172fbc28 100644 --- a/crates/revm/src/custom_upcode.rs +++ b/crates/revm/src/custom_upcode.rs @@ -6,13 +6,13 @@ use revm_interpreter::{ use crate::{ handler::register::EvmHandler, - primitives::{db::Database, ChainSpec, HaltReason, Spec, SpecId}, + primitives::{db::Database, EvmWiring, HaltReason, Spec, SpecId}, }; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct CustomOpcodeChainSpec; +pub struct CustomOpcodeEvmWiring; -impl ChainSpec for CustomOpcodeChainSpec { +impl EvmWiring for CustomOpcodeEvmWiring { type Hardfork = CustomOpcodeSpecId; type HaltReason = HaltReason; } @@ -215,7 +215,7 @@ macro_rules! custom_opcode_spec_to_generic { }}; } -impl EvmHandler<'_, CustomOpcodeChainSpec, EXT, DB> { +impl EvmHandler<'_, CustomOpcodeEvmWiring, EXT, DB> { pub fn custom_opcode_with_spec(spec_id: CustomOpcodeSpecId) -> Self { let mut handler = Self::mainnet_with_spec(spec_id); @@ -229,7 +229,7 @@ impl EvmHandler<'_, CustomOpcodeChainSpec, EXT, DB> { } fn make_custom_instruction_table< - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, H: Host + ?Sized, SPEC: CustomOpcodeSpec, >() -> InstructionTable { @@ -242,7 +242,7 @@ fn make_custom_instruction_table< } fn custom_opcode_handler< - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, H: Host + ?Sized, SPEC: CustomOpcodeSpec, >( diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index b3f358914f..196565bb66 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -204,7 +204,7 @@ impl State { /// NOTE: If either: /// * The [State] has not been built with [StateBuilder::with_bundle_update], or /// * The [State] has a [TransitionState] set to `None` when - /// [State::merge_transitions] is called, + /// [State::merge_transitions] is called, /// /// this will panic. pub fn take_bundle(&mut self) -> BundleState { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index d769db1022..8228635eb4 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -3,13 +3,13 @@ use revm_interpreter::Host as _; use crate::{ builder::{EvmBuilder, HandlerStage, SetGenericStage}, db::{Database, DatabaseCommit, EmptyDB}, - handler::{EnvWithChainSpec, Handler}, + handler::{EnvWithEvmWiring, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthChainSpec, ExecutionResult, + CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthEvmWiring, ExecutionResult, ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, }, - ChainSpec, Context, ContextWithChainSpec, Frame, FrameOrResult, FrameResult, + Context, ContextWithEvmWiring, EvmWiring, Frame, FrameOrResult, FrameResult, }; use core::fmt::{self, Debug}; use std::{boxed::Box, vec::Vec}; @@ -19,17 +19,17 @@ pub const CALL_STACK_LIMIT: u64 = 1024; /// EVM instance containing both internal EVM context and external context /// and the handler that dictates the logic of EVM (or hardfork specification). -pub struct Evm<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { +pub struct Evm<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { /// Context of execution, containing both EVM and external context. - pub context: Context, + pub context: Context, /// Handler is a component of the of EVM that contains all the logic. Handler contains specification id /// and it different depending on the specified fork. - pub handler: Handler<'a, ChainSpecT, Context, EXT, DB>, + pub handler: Handler<'a, EvmWiringT, Context, EXT, DB>, } -impl Debug for Evm<'_, ChainSpecT, EXT, DB> +impl Debug for Evm<'_, EvmWiringT, EXT, DB> where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, EXT: Debug, DB: Database + Debug, { @@ -40,30 +40,30 @@ where } } -impl Evm<'_, ChainSpecT, EXT, DB> { +impl Evm<'_, EvmWiringT, EXT, DB> { /// Commit the changes to the database. pub fn transact_commit( &mut self, - ) -> EVMResultGeneric, ChainSpecT, DB::Error> { + ) -> EVMResultGeneric, EvmWiringT, DB::Error> { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) } } -impl<'a> Evm<'a, EthChainSpec, (), EmptyDB> { +impl<'a> Evm<'a, EthEvmWiring, (), EmptyDB> { /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. - pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthChainSpec, (), EmptyDB> { + pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthEvmWiring, (), EmptyDB> { EvmBuilder::default() } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> Evm<'a, EvmWiringT, EXT, DB> { /// Create new EVM. pub fn new( - mut context: Context, - handler: Handler<'a, ChainSpecT, Context, EXT, DB>, - ) -> Evm<'a, ChainSpecT, EXT, DB> { + mut context: Context, + handler: Handler<'a, EvmWiringT, Context, EXT, DB>, + ) -> Evm<'a, EvmWiringT, EXT, DB> { context .evm .journaled_state @@ -73,7 +73,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> /// Allow for evm setting to be modified by feeding current evm /// into the builder for modifications. - pub fn modify(self) -> EvmBuilder<'a, HandlerStage, ChainSpecT, EXT, DB> { + pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { EvmBuilder::new(self) } @@ -82,7 +82,7 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> pub fn run_the_loop( &mut self, first_frame: Frame, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { let mut call_stack: Vec = Vec::with_capacity(1025); call_stack.push(first_frame); @@ -176,18 +176,18 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> Evm<'a, ChainSpecT, EXT, DB> } } -impl Evm<'_, ChainSpecT, EXT, DB> { +impl Evm<'_, EvmWiringT, EXT, DB> { /// Returns specification (hardfork) that the EVM is instanced with. /// /// SpecId depends on the handler. - pub fn spec_id(&self) -> ChainSpecT::Hardfork { + pub fn spec_id(&self) -> EvmWiringT::Hardfork { self.handler.spec_id } /// Pre verify transaction by checking Environment, initial gas spend and if caller /// has enough balance to pay for the gas. #[inline] - pub fn preverify_transaction(&mut self) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + pub fn preverify_transaction(&mut self) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { let output = self.preverify_transaction_inner().map(|_| ()); self.clear(); output @@ -202,7 +202,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// /// This function will not validate the transaction. #[inline] - pub fn transact_preverified(&mut self) -> EVMResult { + pub fn transact_preverified(&mut self) -> EVMResult { let initial_gas_spend = self .handler .validation() @@ -219,7 +219,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Pre verify transaction inner. #[inline] - fn preverify_transaction_inner(&mut self) -> EVMResultGeneric { + fn preverify_transaction_inner(&mut self) -> EVMResultGeneric { self.handler.validation().env(&self.context.evm.env)?; let initial_gas_spend = self .handler @@ -235,7 +235,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// /// This function will validate the transaction. #[inline] - pub fn transact(&mut self) -> EVMResult { + pub fn transact(&mut self) -> EVMResult { let initial_gas_spend = self.preverify_transaction_inner().map_err(|e| { self.clear(); e @@ -261,13 +261,13 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Returns the reference of transaction #[inline] - pub fn tx(&self) -> &ChainSpecT::Transaction { + pub fn tx(&self) -> &EvmWiringT::Transaction { &self.context.evm.env.tx } /// Returns the mutable reference of transaction #[inline] - pub fn tx_mut(&mut self) -> &mut ChainSpecT::Transaction { + pub fn tx_mut(&mut self) -> &mut EvmWiringT::Transaction { &mut self.context.evm.env.tx } @@ -285,28 +285,28 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Returns the reference of block #[inline] - pub fn block(&self) -> &ChainSpecT::Block { + pub fn block(&self) -> &EvmWiringT::Block { &self.context.evm.env.block } /// Returns the mutable reference of block #[inline] - pub fn block_mut(&mut self) -> &mut ChainSpecT::Block { + pub fn block_mut(&mut self) -> &mut EvmWiringT::Block { &mut self.context.evm.env.block } /// Returns internal database and external struct. #[inline] - pub fn into_context(self) -> Context { + pub fn into_context(self) -> Context { self.context } - /// Returns database and [`EnvWithChainSpec`]. + /// Returns database and [`EnvWithEvmWiring`]. #[inline] - pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithChainSpec) { + pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithEvmWiring) { ( self.context.evm.inner.db, - EnvWithChainSpec { + EnvWithEvmWiring { env: self.context.evm.inner.env, spec_id: self.handler.spec_id, }, @@ -315,15 +315,15 @@ impl Evm<'_, ChainSpecT, EXT, DB> { /// Returns [Context] and hardfork. #[inline] - pub fn into_context_with_spec_id(self) -> ContextWithChainSpec { - ContextWithChainSpec::new(self.context, self.handler.spec_id) + pub fn into_context_with_spec_id(self) -> ContextWithEvmWiring { + ContextWithEvmWiring::new(self.context, self.handler.spec_id) } /// Transact pre-verified transaction. fn transact_preverified_inner( &mut self, initial_gas_spend: u64, - ) -> EVMResult { + ) -> EVMResult { let spec_id = self.spec_id(); let ctx = &mut self.context; let pre_exec = self.handler.pre_execution(); @@ -354,7 +354,7 @@ impl Evm<'_, ChainSpecT, EXT, DB> { { exec.eofcreate( ctx, - Box::new(EOFCreateInputs::new_tx::( + Box::new(EOFCreateInputs::new_tx::( &ctx.evm.env.tx, gas_limit, )), diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index be44ef16eb..acca12cc8f 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -5,7 +5,7 @@ pub mod mainnet; pub mod register; // Exports. -pub use cfg::{CfgEnvWithChainSpec, EnvWithChainSpec}; +pub use cfg::{CfgEnvWithEvmWiring, EnvWithEvmWiring}; pub use handle_types::*; // Includes. @@ -14,7 +14,7 @@ use crate::{ primitives::{ db::Database, spec_to_generic, EVMResultGeneric, InvalidTransaction, TransactionValidation, }, - ChainSpec, Context, Frame, + Context, EvmWiring, Frame, }; use core::mem; use register::{EvmHandler, HandleRegisters}; @@ -25,31 +25,31 @@ use self::register::{HandleRegister, HandleRegisterBox}; /// Handler acts as a proxy and allow to define different behavior for different /// sections of the code. This allows nice integration of different chains or /// to disable some mainnet behavior. -pub struct Handler<'a, ChainSpecT: ChainSpec, H: Host + 'a, EXT, DB: Database> { +pub struct Handler<'a, EvmWiringT: EvmWiring, H: Host + 'a, EXT, DB: Database> { /// Handler hardfork - pub spec_id: ChainSpecT::Hardfork, + pub spec_id: EvmWiringT::Hardfork, /// Instruction table type. pub instruction_table: InstructionTables<'a, H>, /// Registers that will be called on initialization. - pub registers: Vec>, + pub registers: Vec>, /// Validity handles. - pub validation: ValidationHandler<'a, ChainSpecT, EXT, DB>, + pub validation: ValidationHandler<'a, EvmWiringT, EXT, DB>, /// Pre execution handle. - pub pre_execution: PreExecutionHandler<'a, ChainSpecT, EXT, DB>, + pub pre_execution: PreExecutionHandler<'a, EvmWiringT, EXT, DB>, /// Post Execution handle. - pub post_execution: PostExecutionHandler<'a, ChainSpecT, EXT, DB>, + pub post_execution: PostExecutionHandler<'a, EvmWiringT, EXT, DB>, /// Execution loop that handles frames. - pub execution: ExecutionHandler<'a, ChainSpecT, EXT, DB>, + pub execution: ExecutionHandler<'a, EvmWiringT, EXT, DB>, } -impl<'a, ChainSpecT, EXT, DB> EvmHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT, EXT, DB> EvmHandler<'a, EvmWiringT, EXT, DB> where - ChainSpecT: - ChainSpec>>, + EvmWiringT: + EvmWiring>>, DB: Database, { /// Creates a base/vanilla Ethereum handler with the provided spec id. - pub fn mainnet_with_spec(spec_id: ChainSpecT::Hardfork) -> Self { + pub fn mainnet_with_spec(spec_id: EvmWiringT::Hardfork) -> Self { spec_to_generic!( spec_id.into(), Self { @@ -65,13 +65,13 @@ where } } -impl<'a, ChainSpecT, EXT, DB> EvmHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT, EXT, DB> EvmHandler<'a, EvmWiringT, EXT, DB> where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, { /// Returns the specification ID. - pub fn spec_id(&self) -> ChainSpecT::Hardfork { + pub fn spec_id(&self) -> EvmWiringT::Hardfork { self.spec_id } @@ -80,8 +80,8 @@ where &self, frame: &mut Frame, shared_memory: &mut SharedMemory, - context: &mut Context, - ) -> EVMResultGeneric { + context: &mut Context, + ) -> EVMResultGeneric { self.execution .execute_frame(frame, shared_memory, &self.instruction_table, context) } @@ -89,7 +89,7 @@ where /// Take instruction table. pub fn take_instruction_table( &mut self, - ) -> InstructionTables<'a, Context> { + ) -> InstructionTables<'a, Context> { let spec_id = self.spec_id(); mem::replace( &mut self.instruction_table, @@ -100,39 +100,39 @@ where /// Set instruction table. pub fn set_instruction_table( &mut self, - table: InstructionTables<'a, Context>, + table: InstructionTables<'a, Context>, ) { self.instruction_table = table; } /// Returns reference to pre execution handler. - pub fn pre_execution(&self) -> &PreExecutionHandler<'a, ChainSpecT, EXT, DB> { + pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EvmWiringT, EXT, DB> { &self.pre_execution } /// Returns reference to pre execution handler. - pub fn post_execution(&self) -> &PostExecutionHandler<'a, ChainSpecT, EXT, DB> { + pub fn post_execution(&self) -> &PostExecutionHandler<'a, EvmWiringT, EXT, DB> { &self.post_execution } /// Returns reference to frame handler. - pub fn execution(&self) -> &ExecutionHandler<'a, ChainSpecT, EXT, DB> { + pub fn execution(&self) -> &ExecutionHandler<'a, EvmWiringT, EXT, DB> { &self.execution } /// Returns reference to validation handler. - pub fn validation(&self) -> &ValidationHandler<'a, ChainSpecT, EXT, DB> { + pub fn validation(&self) -> &ValidationHandler<'a, EvmWiringT, EXT, DB> { &self.validation } /// Append handle register. - pub fn append_handler_register(&mut self, register: HandleRegisters<'a, ChainSpecT, EXT, DB>) { + pub fn append_handler_register(&mut self, register: HandleRegisters<'a, EvmWiringT, EXT, DB>) { register.register(self); self.registers.push(register); } /// Append plain handle register. - pub fn append_handler_register_plain(&mut self, register: HandleRegister) { + pub fn append_handler_register_plain(&mut self, register: HandleRegister) { register(self); self.registers.push(HandleRegisters::Plain(register)); } @@ -140,25 +140,25 @@ where /// Append boxed handle register. pub fn append_handler_register_box( &mut self, - register: HandleRegisterBox<'a, ChainSpecT, EXT, DB>, + register: HandleRegisterBox<'a, EvmWiringT, EXT, DB>, ) { register(self); self.registers.push(HandleRegisters::Box(register)); } } -impl<'a, ChainSpecT, EXT, DB> EvmHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT, EXT, DB> EvmHandler<'a, EvmWiringT, EXT, DB> where - ChainSpecT: - ChainSpec>>, + EvmWiringT: + EvmWiring>>, DB: Database, { /// Pop last handle register and reapply all registers that are left. - pub fn pop_handle_register(&mut self) -> Option> { + pub fn pop_handle_register(&mut self) -> Option> { let out = self.registers.pop(); if out.is_some() { let registers = core::mem::take(&mut self.registers); - let mut base_handler = ChainSpecT::handler::<'a, EXT, DB>(self.spec_id); + let mut base_handler = EvmWiringT::handler::<'a, EXT, DB>(self.spec_id); // apply all registers to default handler and raw mainnet instruction table. for register in registers { base_handler.append_handler_register(register) @@ -169,14 +169,14 @@ where } /// Creates the Handler with variable SpecId, inside it will call function with Generic Spec. - pub fn modify_spec_id(&mut self, spec_id: ChainSpecT::Hardfork) { + pub fn modify_spec_id(&mut self, spec_id: EvmWiringT::Hardfork) { if self.spec_id == spec_id { return; } let registers = core::mem::take(&mut self.registers); // register for optimism is added as a register, so we need to create mainnet handler here. - let mut handler = ChainSpecT::handler::<'a, EXT, DB>(spec_id); + let mut handler = EvmWiringT::handler::<'a, EXT, DB>(spec_id); // apply all registers to default handler and raw mainnet instruction table. for register in registers { handler.append_handler_register(register) @@ -199,14 +199,14 @@ mod test { use super::*; #[cfg(feature = "optimism")] - type TestChainSpec = crate::optimism::ChainSpec; + type TestEvmWiring = crate::optimism::EvmWiring; #[cfg(not(feature = "optimism"))] - type TestChainSpec = primitives::EthChainSpec; + type TestEvmWiring = primitives::EthEvmWiring; #[test] fn test_handler_register_pop() { let register = - |inner: &Rc>| -> HandleRegisterBox<'_, TestChainSpec, (), EmptyDB> { + |inner: &Rc>| -> HandleRegisterBox<'_, TestEvmWiring, (), EmptyDB> { let inner = inner.clone(); Box::new(move |h| { *inner.borrow_mut() += 1; @@ -215,8 +215,8 @@ mod test { }) }; - let mut handler = EvmHandler::<'_, TestChainSpec, (), EmptyDB>::mainnet_with_spec( - ::Hardfork::default(), + let mut handler = EvmHandler::<'_, TestEvmWiring, (), EmptyDB>::mainnet_with_spec( + ::Hardfork::default(), ); let test = Rc::new(RefCell::new(0)); diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs index bc64c24724..fc1ea52c56 100644 --- a/crates/revm/src/handler/cfg.rs +++ b/crates/revm/src/handler/cfg.rs @@ -6,32 +6,32 @@ use std::boxed::Box; use derive_where::derive_where; -use crate::primitives::{CfgEnv, ChainSpec, Env}; +use crate::primitives::{CfgEnv, Env, EvmWiring}; /// Configuration environment with the chain spec id. #[derive(Debug, Eq, PartialEq)] -#[derive_where(Clone; ChainSpecT::Hardfork)] -pub struct CfgEnvWithChainSpec { +#[derive_where(Clone; EvmWiringT::Hardfork)] +pub struct CfgEnvWithEvmWiring { /// Configuration environment. pub cfg_env: CfgEnv, /// Handler configuration fields. - pub spec_id: ChainSpecT::Hardfork, + pub spec_id: EvmWiringT::Hardfork, } -impl CfgEnvWithChainSpec { +impl CfgEnvWithEvmWiring { /// Returns new instance of `CfgEnvWithHandlerCfg`. - pub fn new(cfg_env: CfgEnv, spec_id: ChainSpecT::Hardfork) -> Self { + pub fn new(cfg_env: CfgEnv, spec_id: EvmWiringT::Hardfork) -> Self { Self { cfg_env, spec_id } } } -impl DerefMut for CfgEnvWithChainSpec { +impl DerefMut for CfgEnvWithEvmWiring { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.cfg_env } } -impl Deref for CfgEnvWithChainSpec { +impl Deref for CfgEnvWithEvmWiring { type Target = CfgEnv; fn deref(&self) -> &Self::Target { @@ -40,55 +40,55 @@ impl Deref for CfgEnvWithChainSpec { } /// Evm environment with the chain spec id. -#[derive_where(Clone, Debug; ChainSpecT::Block, ChainSpecT::Hardfork, ChainSpecT::Transaction)] -pub struct EnvWithChainSpec +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Hardfork, EvmWiringT::Transaction)] +pub struct EnvWithEvmWiring where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { /// Evm enironment. - pub env: Box>, + pub env: Box>, /// Handler configuration fields. - pub spec_id: ChainSpecT::Hardfork, + pub spec_id: EvmWiringT::Hardfork, } -impl EnvWithChainSpec +impl EnvWithEvmWiring where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { /// Returns new `EnvWithHandlerCfg` instance. - pub fn new(env: Box>, spec_id: ChainSpecT::Hardfork) -> Self { + pub fn new(env: Box>, spec_id: EvmWiringT::Hardfork) -> Self { Self { env, spec_id } } /// Takes `CfgEnvWithHandlerCfg` and returns new `EnvWithHandlerCfg` instance. pub fn new_with_cfg_env( - cfg: CfgEnvWithChainSpec, - block: ChainSpecT::Block, - tx: ChainSpecT::Transaction, + cfg: CfgEnvWithEvmWiring, + block: EvmWiringT::Block, + tx: EvmWiringT::Transaction, ) -> Self { Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.spec_id) } /// Returns the specification id. - pub const fn spec_id(&self) -> ChainSpecT::Hardfork { + pub const fn spec_id(&self) -> EvmWiringT::Hardfork { self.spec_id } } -impl DerefMut for EnvWithChainSpec +impl DerefMut for EnvWithEvmWiring where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.env } } -impl Deref for EnvWithChainSpec +impl Deref for EnvWithEvmWiring where - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, { - type Target = Env; + type Target = Env; fn deref(&self) -> &Self::Target { &self.env diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index 03dc4125a3..271e7bac48 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -3,7 +3,7 @@ use crate::{ handler::mainnet, interpreter::{CallInputs, CreateInputs, SharedMemory}, primitives::{db::Database, EVMResultGeneric, Spec}, - CallFrame, ChainSpec, Context, CreateFrame, Frame, FrameOrResult, FrameResult, + CallFrame, Context, CreateFrame, EvmWiring, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInputs, InterpreterAction, @@ -12,171 +12,171 @@ use revm_interpreter::{ use std::{boxed::Box, sync::Arc}; /// Handles first frame return handle. -pub type LastFrameReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type LastFrameReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut FrameResult, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Executes a single frame. Errors can be returned in the EVM context. -pub type ExecuteFrameHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type ExecuteFrameHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( &mut Frame, &mut SharedMemory, - &InstructionTables<'_, Context>, - &mut Context, - ) -> EVMResultGeneric::Error> + &InstructionTables<'_, Context>, + &mut Context, + ) -> EVMResultGeneric::Error> + 'a, >; /// Handle sub call. -pub type FrameCallHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type FrameCallHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric::Error> + 'a, >; /// Handle call return -pub type FrameCallReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type FrameCallReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric::Error> + 'a, >; /// Insert call outcome to the parent -pub type InsertCallOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type InsertCallOutcomeHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, &mut SharedMemory, CallOutcome, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Handle sub create. -pub type FrameCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type FrameCreateHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric::Error> + 'a, >; /// Handle create return -pub type FrameCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type FrameCreateReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric::Error> + 'a, >; /// Insert call outcome to the parent -pub type InsertCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type InsertCreateOutcomeHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, CreateOutcome, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Handle EOF sub create. -pub type FrameEOFCreateHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type FrameEOFCreateHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric::Error> + 'a, >; /// Handle EOF create return -pub type FrameEOFCreateReturnHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type FrameEOFCreateReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric::Error> + 'a, >; /// Insert EOF crate outcome to the parent -pub type InsertEOFCreateOutcomeHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type InsertEOFCreateOutcomeHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, CreateOutcome, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Handles related to stack frames. -pub struct ExecutionHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { +pub struct ExecutionHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { /// Handles last frame return, modified gas for refund and /// sets tx gas limit. - pub last_frame_return: LastFrameReturnHandle<'a, ChainSpecT, EXT, DB>, + pub last_frame_return: LastFrameReturnHandle<'a, EvmWiringT, EXT, DB>, /// Executes a single frame. - pub execute_frame: ExecuteFrameHandle<'a, ChainSpecT, EXT, DB>, + pub execute_frame: ExecuteFrameHandle<'a, EvmWiringT, EXT, DB>, /// Frame call - pub call: FrameCallHandle<'a, ChainSpecT, EXT, DB>, + pub call: FrameCallHandle<'a, EvmWiringT, EXT, DB>, /// Call return - pub call_return: FrameCallReturnHandle<'a, ChainSpecT, EXT, DB>, + pub call_return: FrameCallReturnHandle<'a, EvmWiringT, EXT, DB>, /// Insert call outcome - pub insert_call_outcome: InsertCallOutcomeHandle<'a, ChainSpecT, EXT, DB>, + pub insert_call_outcome: InsertCallOutcomeHandle<'a, EvmWiringT, EXT, DB>, /// Frame crate - pub create: FrameCreateHandle<'a, ChainSpecT, EXT, DB>, + pub create: FrameCreateHandle<'a, EvmWiringT, EXT, DB>, /// Crate return - pub create_return: FrameCreateReturnHandle<'a, ChainSpecT, EXT, DB>, + pub create_return: FrameCreateReturnHandle<'a, EvmWiringT, EXT, DB>, /// Insert create outcome. - pub insert_create_outcome: InsertCreateOutcomeHandle<'a, ChainSpecT, EXT, DB>, + pub insert_create_outcome: InsertCreateOutcomeHandle<'a, EvmWiringT, EXT, DB>, /// Frame EOFCreate - pub eofcreate: FrameEOFCreateHandle<'a, ChainSpecT, EXT, DB>, + pub eofcreate: FrameEOFCreateHandle<'a, EvmWiringT, EXT, DB>, /// EOFCreate return - pub eofcreate_return: FrameEOFCreateReturnHandle<'a, ChainSpecT, EXT, DB>, + pub eofcreate_return: FrameEOFCreateReturnHandle<'a, EvmWiringT, EXT, DB>, /// Insert EOFCreate outcome. - pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, ChainSpecT, EXT, DB>, + pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, EvmWiringT, EXT, DB>, } -impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> - ExecutionHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> + ExecutionHandler<'a, EvmWiringT, EXT, DB> { /// Creates mainnet ExecutionHandler. pub fn new() -> Self { Self { - last_frame_return: Arc::new(mainnet::last_frame_return::), - execute_frame: Arc::new(mainnet::execute_frame::), - call: Arc::new(mainnet::call::), - call_return: Arc::new(mainnet::call_return::), + last_frame_return: Arc::new(mainnet::last_frame_return::), + execute_frame: Arc::new(mainnet::execute_frame::), + call: Arc::new(mainnet::call::), + call_return: Arc::new(mainnet::call_return::), insert_call_outcome: Arc::new(mainnet::insert_call_outcome), - create: Arc::new(mainnet::create::), - create_return: Arc::new(mainnet::create_return::), + create: Arc::new(mainnet::create::), + create_return: Arc::new(mainnet::create_return::), insert_create_outcome: Arc::new(mainnet::insert_create_outcome), - eofcreate: Arc::new(mainnet::eofcreate::), - eofcreate_return: Arc::new(mainnet::eofcreate_return::), + eofcreate: Arc::new(mainnet::eofcreate::), + eofcreate_return: Arc::new(mainnet::eofcreate_return::), insert_eofcreate_outcome: Arc::new(mainnet::insert_eofcreate_outcome), } } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpecT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWiringT, EXT, DB> { /// Executes single frame. #[inline] pub fn execute_frame( &self, frame: &mut Frame, shared_memory: &mut SharedMemory, - instruction_tables: &InstructionTables<'_, Context>, - context: &mut Context, - ) -> EVMResultGeneric { + instruction_tables: &InstructionTables<'_, Context>, + context: &mut Context, + ) -> EVMResultGeneric { (self.execute_frame)(frame, shared_memory, instruction_tables, context) } @@ -184,9 +184,9 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn last_frame_return( &self, - context: &mut Context, + context: &mut Context, frame_result: &mut FrameResult, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.last_frame_return)(context, frame_result) } @@ -194,9 +194,9 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn call( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.call)(context, inputs) } @@ -204,10 +204,10 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn call_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.call_return)(context, frame, interpreter_result) } @@ -215,11 +215,11 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn insert_call_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.insert_call_outcome)(context, frame, shared_memory, outcome) } @@ -227,9 +227,9 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn create( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.create)(context, inputs) } @@ -237,10 +237,10 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn create_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.create_return)(context, frame, interpreter_result) } @@ -248,10 +248,10 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn insert_create_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.insert_create_outcome)(context, frame, outcome) } @@ -259,9 +259,9 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn eofcreate( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.eofcreate)(context, inputs) } @@ -269,10 +269,10 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn eofcreate_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.eofcreate_return)(context, frame, interpreter_result) } @@ -280,10 +280,10 @@ impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ExecutionHandler<'a, ChainSpe #[inline] pub fn insert_eofcreate_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.insert_eofcreate_outcome)(context, frame, outcome) } } diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index d87d5c1d6f..3bb2a6f166 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -3,30 +3,30 @@ use crate::{ handler::mainnet, interpreter::Gas, primitives::{db::Database, EVMResultGeneric, ResultAndState, Spec}, - ChainSpec, Context, FrameResult, + Context, EvmWiring, FrameResult, }; use std::sync::Arc; /// Reimburse the caller with ethereum it didn't spent. -pub type ReimburseCallerHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type ReimburseCallerHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, &Gas, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Reward beneficiary with transaction rewards. -pub type RewardBeneficiaryHandle<'a, ChainSpecT, EXT, DB> = - ReimburseCallerHandle<'a, ChainSpecT, EXT, DB>; +pub type RewardBeneficiaryHandle<'a, EvmWiringT, EXT, DB> = + ReimburseCallerHandle<'a, EvmWiringT, EXT, DB>; /// Main return handle, takes state from journal and transforms internal result to external. -pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type OutputHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, + &mut Context, FrameResult, ) - -> EVMResultGeneric, ChainSpecT, ::Error> + -> EVMResultGeneric, EvmWiringT, ::Error> + 'a, >; @@ -34,89 +34,89 @@ pub type OutputHandle<'a, ChainSpecT, EXT, DB> = Arc< /// This will be called after all the other handlers. /// /// It is useful for catching errors and returning them in a different way. -pub type EndHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type EndHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, - EVMResultGeneric, ChainSpecT, ::Error>, + &mut Context, + EVMResultGeneric, EvmWiringT, ::Error>, ) - -> EVMResultGeneric, ChainSpecT, ::Error> + -> EVMResultGeneric, EvmWiringT, ::Error> + 'a, >; /// Clear handle, doesn't have output, its purpose is to clear the /// context. It will always be called even on failed validation. -pub type ClearHandle<'a, ChainSpecT, EXT, DB> = Arc) + 'a>; +pub type ClearHandle<'a, EvmWiringT, EXT, DB> = Arc) + 'a>; /// Handles related to post execution after the stack loop is finished. -pub struct PostExecutionHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { +pub struct PostExecutionHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { /// Reimburse the caller with ethereum it didn't spend. - pub reimburse_caller: ReimburseCallerHandle<'a, ChainSpecT, EXT, DB>, + pub reimburse_caller: ReimburseCallerHandle<'a, EvmWiringT, EXT, DB>, /// Reward the beneficiary with caller fee. - pub reward_beneficiary: RewardBeneficiaryHandle<'a, ChainSpecT, EXT, DB>, + pub reward_beneficiary: RewardBeneficiaryHandle<'a, EvmWiringT, EXT, DB>, /// Main return handle, returns the output of the transact. - pub output: OutputHandle<'a, ChainSpecT, EXT, DB>, + pub output: OutputHandle<'a, EvmWiringT, EXT, DB>, /// Called when execution ends. /// End handle in comparison to output handle will be called every time after execution. /// Output in case of error will not be called. - pub end: EndHandle<'a, ChainSpecT, EXT, DB>, + pub end: EndHandle<'a, EvmWiringT, EXT, DB>, /// Clear handle will be called always. In comparison to end that /// is called only on execution end, clear handle is called even if validation fails. - pub clear: ClearHandle<'a, ChainSpecT, EXT, DB>, + pub clear: ClearHandle<'a, EvmWiringT, EXT, DB>, } -impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> - PostExecutionHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> + PostExecutionHandler<'a, EvmWiringT, EXT, DB> { /// Creates mainnet MainHandles. pub fn mainnet() -> Self { Self { - reimburse_caller: Arc::new(mainnet::reimburse_caller::), - reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), - output: Arc::new(mainnet::output::), - end: Arc::new(mainnet::end::), - clear: Arc::new(mainnet::clear::), + reimburse_caller: Arc::new(mainnet::reimburse_caller::), + reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), + output: Arc::new(mainnet::output::), + end: Arc::new(mainnet::end::), + clear: Arc::new(mainnet::clear::), } } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PostExecutionHandler<'a, ChainSpecT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> PostExecutionHandler<'a, EvmWiringT, EXT, DB> { /// Reimburse the caller with gas that were not spend. pub fn reimburse_caller( &self, - context: &mut Context, + context: &mut Context, gas: &Gas, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.reimburse_caller)(context, gas) } /// Reward beneficiary pub fn reward_beneficiary( &self, - context: &mut Context, + context: &mut Context, gas: &Gas, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.reward_beneficiary)(context, gas) } /// Returns the output of transaction. pub fn output( &self, - context: &mut Context, + context: &mut Context, result: FrameResult, - ) -> EVMResultGeneric, ChainSpecT, DB::Error> { + ) -> EVMResultGeneric, EvmWiringT, DB::Error> { (self.output)(context, result) } /// End handler. pub fn end( &self, - context: &mut Context, - end_output: EVMResultGeneric, ChainSpecT, DB::Error>, - ) -> EVMResultGeneric, ChainSpecT, DB::Error> { + context: &mut Context, + end_output: EVMResultGeneric, EvmWiringT, DB::Error>, + ) -> EVMResultGeneric, EvmWiringT, DB::Error> { (self.end)(context, end_output) } /// Clean handler. - pub fn clear(&self, context: &mut Context) { + pub fn clear(&self, context: &mut Context) { (self.clear)(context) } } diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 38b0d746ef..30094637f7 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -2,74 +2,74 @@ use crate::{ handler::mainnet, primitives::{db::Database, EVMResultGeneric, Spec}, - ChainSpec, Context, ContextPrecompiles, + Context, ContextPrecompiles, EvmWiring, }; use std::sync::Arc; /// Loads precompiles into Evm -pub type LoadPrecompilesHandle<'a, ChainSpecT, DB> = - Arc ContextPrecompiles + 'a>; +pub type LoadPrecompilesHandle<'a, EvmWiringT, DB> = + Arc ContextPrecompiles + 'a>; /// Load access list accounts and beneficiary. /// There is no need to load Caller as it is assumed that /// it will be loaded in DeductCallerHandle. -pub type LoadAccountsHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type LoadAccountsHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Deduct the caller to its limit. -pub type DeductCallerHandle<'a, ChainSpecT, EXT, DB> = Arc< +pub type DeductCallerHandle<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Handles related to pre execution before the stack loop is started. -pub struct PreExecutionHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { +pub struct PreExecutionHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { /// Load precompiles - pub load_precompiles: LoadPrecompilesHandle<'a, ChainSpecT, DB>, + pub load_precompiles: LoadPrecompilesHandle<'a, EvmWiringT, DB>, /// Main load handle - pub load_accounts: LoadAccountsHandle<'a, ChainSpecT, EXT, DB>, + pub load_accounts: LoadAccountsHandle<'a, EvmWiringT, EXT, DB>, /// Deduct max value from the caller. - pub deduct_caller: DeductCallerHandle<'a, ChainSpecT, EXT, DB>, + pub deduct_caller: DeductCallerHandle<'a, EvmWiringT, EXT, DB>, } -impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> - PreExecutionHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> + PreExecutionHandler<'a, EvmWiringT, EXT, DB> { /// Creates mainnet MainHandles. pub fn new() -> Self { Self { - load_precompiles: Arc::new(mainnet::load_precompiles::), - load_accounts: Arc::new(mainnet::load_accounts::), - deduct_caller: Arc::new(mainnet::deduct_caller::), + load_precompiles: Arc::new(mainnet::load_precompiles::), + load_accounts: Arc::new(mainnet::load_accounts::), + deduct_caller: Arc::new(mainnet::deduct_caller::), } } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> PreExecutionHandler<'a, ChainSpecT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> PreExecutionHandler<'a, EvmWiringT, EXT, DB> { /// Deduct caller to its limit. pub fn deduct_caller( &self, - context: &mut Context, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + context: &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.deduct_caller)(context) } /// Main load pub fn load_accounts( &self, - context: &mut Context, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + context: &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.load_accounts)(context) } /// Load precompiles - pub fn load_precompiles(&self) -> ContextPrecompiles { + pub fn load_precompiles(&self) -> ContextPrecompiles { (self.load_precompiles)() } } diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index a69be9508c..b1217d7db4 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -3,74 +3,74 @@ use crate::{ primitives::{ db::Database, EVMResultGeneric, Env, InvalidTransaction, Spec, TransactionValidation, }, - ChainSpec, Context, + Context, EvmWiring, }; use std::sync::Arc; /// Handle that validates env. -pub type ValidateEnvHandle<'a, ChainSpecT, DB> = - Arc) -> EVMResultGeneric<(), ChainSpecT, ::Error> + 'a>; +pub type ValidateEnvHandle<'a, EvmWiringT, DB> = + Arc) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a>; /// Handle that validates transaction environment against the state. /// Second parametar is initial gas. -pub type ValidateTxEnvAgainstState<'a, ChainSpecT, EXT, DB> = Arc< +pub type ValidateTxEnvAgainstState<'a, EvmWiringT, EXT, DB> = Arc< dyn Fn( - &mut Context, - ) -> EVMResultGeneric<(), ChainSpecT, ::Error> + &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a, >; /// Initial gas calculation handle -pub type ValidateInitialTxGasHandle<'a, ChainSpecT, DB> = Arc< - dyn Fn(&Env) -> EVMResultGeneric::Error> + 'a, +pub type ValidateInitialTxGasHandle<'a, EvmWiringT, DB> = Arc< + dyn Fn(&Env) -> EVMResultGeneric::Error> + 'a, >; /// Handles related to validation. -pub struct ValidationHandler<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { +pub struct ValidationHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { /// Validate and calculate initial transaction gas. - pub initial_tx_gas: ValidateInitialTxGasHandle<'a, ChainSpecT, DB>, + pub initial_tx_gas: ValidateInitialTxGasHandle<'a, EvmWiringT, DB>, /// Validate transactions against state data. - pub tx_against_state: ValidateTxEnvAgainstState<'a, ChainSpecT, EXT, DB>, + pub tx_against_state: ValidateTxEnvAgainstState<'a, EvmWiringT, EXT, DB>, /// Validate Env. - pub env: ValidateEnvHandle<'a, ChainSpecT, DB>, + pub env: ValidateEnvHandle<'a, EvmWiringT, DB>, } -impl<'a, ChainSpecT: ChainSpec, EXT: 'a, DB: Database + 'a> - ValidationHandler<'a, ChainSpecT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> + ValidationHandler<'a, EvmWiringT, EXT, DB> where - ::ValidationError: From, + ::ValidationError: From, { /// Create new ValidationHandles pub fn new() -> Self { Self { - initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), - env: Arc::new(mainnet::validate_env::), + initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), + env: Arc::new(mainnet::validate_env::), tx_against_state: Arc::new( - mainnet::validate_tx_against_state::, + mainnet::validate_tx_against_state::, ), } } } -impl<'a, ChainSpecT: ChainSpec, EXT, DB: Database> ValidationHandler<'a, ChainSpecT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ValidationHandler<'a, EvmWiringT, EXT, DB> { /// Validate env. - pub fn env(&self, env: &Env) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + pub fn env(&self, env: &Env) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.env)(env) } /// Initial gas pub fn initial_tx_gas( &self, - env: &Env, - ) -> EVMResultGeneric { + env: &Env, + ) -> EVMResultGeneric { (self.initial_tx_gas)(env) } /// Validate ttansaction against the state. pub fn tx_against_state( &self, - context: &mut Context, - ) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { + context: &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { (self.tx_against_state)(context) } } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 462e843ba1..0b3c4dcb42 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -6,7 +6,7 @@ use crate::{ SharedMemory, }, primitives::{EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction}, - CallFrame, ChainSpec, Context, CreateFrame, Frame, FrameOrResult, FrameResult, + CallFrame, Context, CreateFrame, EvmWiring, Frame, FrameOrResult, FrameResult, }; use core::mem; use revm_interpreter::{ @@ -17,12 +17,12 @@ use std::boxed::Box; /// Execute frame #[inline] -pub fn execute_frame( +pub fn execute_frame( frame: &mut Frame, shared_memory: &mut SharedMemory, - instruction_tables: &InstructionTables<'_, Context>, - context: &mut Context, -) -> EVMResultGeneric { + instruction_tables: &InstructionTables<'_, Context>, + context: &mut Context, +) -> EVMResultGeneric { let interpreter = frame.interpreter_mut(); let memory = mem::replace(shared_memory, EMPTY_SHARED_MEMORY); let next_action = match instruction_tables { @@ -37,8 +37,8 @@ pub fn execute_frame( /// Helper function called inside [`last_frame_return`] #[inline] -pub fn frame_return_with_refund_flag( - env: &Env, +pub fn frame_return_with_refund_flag( + env: &Env, frame_result: &mut FrameResult, refund_enabled: bool, ) { @@ -73,29 +73,29 @@ pub fn frame_return_with_refund_flag( /// Handle output of the transaction #[inline] -pub fn last_frame_return( - context: &mut Context, +pub fn last_frame_return( + context: &mut Context, frame_result: &mut FrameResult, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { - frame_return_with_refund_flag::(&context.evm.env, frame_result, true); +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + frame_return_with_refund_flag::(&context.evm.env, frame_result, true); Ok(()) } /// Handle frame sub call. #[inline] -pub fn call( - context: &mut Context, +pub fn call( + context: &mut Context, inputs: Box, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context.evm.make_call_frame(&inputs) } #[inline] -pub fn call_return( - context: &mut Context, +pub fn call_return( + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context .evm .call_return(&interpreter_result, frame.frame_data.checkpoint); @@ -106,12 +106,12 @@ pub fn call_return( } #[inline] -pub fn insert_call_outcome( - context: &mut Context, +pub fn insert_call_outcome( + context: &mut Context, frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -123,10 +123,10 @@ pub fn insert_call_outcome( /// Handle frame sub create. #[inline] -pub fn create( - context: &mut Context, +pub fn create( + context: &mut Context, inputs: Box, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context .evm .make_create_frame(SPEC::SPEC_ID, &inputs) @@ -134,11 +134,11 @@ pub fn create( } #[inline] -pub fn create_return( - context: &mut Context, +pub fn create_return( + context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context.evm.create_return::( &mut interpreter_result, frame.created_address, @@ -151,11 +151,11 @@ pub fn create_return( } #[inline] -pub fn insert_create_outcome( - context: &mut Context, +pub fn insert_create_outcome( + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -167,10 +167,10 @@ pub fn insert_create_outcome( /// Handle frame sub create. #[inline] -pub fn eofcreate( - context: &mut Context, +pub fn eofcreate( + context: &mut Context, inputs: Box, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context .evm .make_eofcreate_frame(SPEC::SPEC_ID, &inputs) @@ -178,11 +178,11 @@ pub fn eofcreate( } #[inline] -pub fn eofcreate_return( - context: &mut Context, +pub fn eofcreate_return( + context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context.evm.eofcreate_return::( &mut interpreter_result, frame.created_address, @@ -195,11 +195,11 @@ pub fn eofcreate_return( } #[inline] -pub fn insert_eofcreate_outcome( - context: &mut Context, +pub fn insert_eofcreate_outcome( + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { core::mem::replace(&mut context.evm.error, Ok(())).map_err(EVMError::Database)?; frame @@ -212,13 +212,13 @@ pub fn insert_eofcreate_outcome( #[cfg(test)] mod tests { use super::*; - use crate::primitives::EthChainSpec; + use crate::primitives::EthEvmWiring; use revm_interpreter::primitives::CancunSpec; use revm_precompile::Bytes; /// Creates frame result. fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.gas_limit = 100; let mut first_frame = FrameResult::Call(CallOutcome::new( @@ -229,7 +229,7 @@ mod tests { }, 0..0, )); - frame_return_with_refund_flag::(&env, &mut first_frame, true); + frame_return_with_refund_flag::(&env, &mut first_frame, true); *first_frame.gas() } diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index ee2f16e56f..3bfb8299c8 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -4,21 +4,21 @@ use crate::{ db::Database, Block, Bytecode, EVMError, EVMResultGeneric, ExecutionResult, ResultAndState, Spec, SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, }, - ChainSpec, Context, FrameResult, + Context, EvmWiring, FrameResult, }; /// Mainnet end handle does not change the output. #[inline] -pub fn end( - _context: &mut Context, - evm_output: EVMResultGeneric, ChainSpecT, DB::Error>, -) -> EVMResultGeneric, ChainSpecT, DB::Error> { +pub fn end( + _context: &mut Context, + evm_output: EVMResultGeneric, EvmWiringT, DB::Error>, +) -> EVMResultGeneric, EvmWiringT, DB::Error> { evm_output } /// Clear handle clears error and journal state. #[inline] -pub fn clear(context: &mut Context) { +pub fn clear(context: &mut Context) { // clear error and journaled state. let _ = context.evm.take_error(); context.evm.inner.journaled_state.clear(); @@ -29,10 +29,10 @@ pub fn clear(context: &mut Context( - context: &mut Context, +pub fn reward_beneficiary( + context: &mut Context, gas: &Gas, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { let beneficiary = *context.evm.env.block.coinbase(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -61,10 +61,10 @@ pub fn reward_beneficiary( } #[inline] -pub fn reimburse_caller( - context: &mut Context, +pub fn reimburse_caller( + context: &mut Context, gas: &Gas, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { let caller = context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -86,10 +86,10 @@ pub fn reimburse_caller( /// Main return handle, returns the output of the transaction. #[inline] -pub fn output( - context: &mut Context, +pub fn output( + context: &mut Context, result: FrameResult, -) -> EVMResultGeneric, ChainSpecT, DB::Error> { +) -> EVMResultGeneric, EvmWiringT, DB::Error> { context.evm.take_error().map_err(EVMError::Database)?; // used gas with refund calculated. @@ -110,7 +110,7 @@ pub fn output( account.info.code_hash = KECCAK_EMPTY; } - let result = match SuccessOrHalt::::from(instruction_result.result) { + let result = match SuccessOrHalt::::from(instruction_result.result) { SuccessOrHalt::Success(reason) => ExecutionResult::Success { reason, gas_used: final_gas_used, diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 610248a85f..e67c4dd233 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -8,22 +8,22 @@ use crate::{ db::Database, Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction as _, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, - ChainSpec, Context, ContextPrecompiles, + Context, ContextPrecompiles, EvmWiring, }; use std::vec::Vec; /// Main precompile load #[inline] -pub fn load_precompiles( -) -> ContextPrecompiles { +pub fn load_precompiles( +) -> ContextPrecompiles { ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) } /// Main load handle #[inline] -pub fn load_accounts( - context: &mut Context, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +pub fn load_accounts( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { // set journaling state flag. context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); @@ -125,9 +125,9 @@ pub fn load_accounts( /// Helper function that deducts the caller balance. #[inline] -pub fn deduct_caller_inner( +pub fn deduct_caller_inner( caller_account: &mut Account, - env: &Env, + env: &Env, ) { // Subtract gas costs from the caller's account. // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. @@ -154,9 +154,9 @@ pub fn deduct_caller_inner( /// Deducts the caller balance to the transaction limit. #[inline] -pub fn deduct_caller( - context: &mut Context, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +pub fn deduct_caller( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { // load caller's account. let (caller_account, _) = context .evm @@ -169,7 +169,7 @@ pub fn deduct_caller( .map_err(EVMError::Database)?; // deduct gas cost from caller's account. - deduct_caller_inner::(caller_account, &context.evm.inner.env); + deduct_caller_inner::(caller_account, &context.evm.inner.env); Ok(()) } diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index eb4bbc4ec1..d7db6058de 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -5,15 +5,15 @@ use crate::{ db::Database, EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, Transaction, TransactionValidation, }, - ChainSpec, Context, + Context, EvmWiring, }; /// Validate environment for the mainnet. -pub fn validate_env( - env: &Env, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> +pub fn validate_env( + env: &Env, +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> where - ::ValidationError: From, + ::ValidationError: From, { // Important: validate block before tx. env.validate_block_env::()?; @@ -23,11 +23,11 @@ where } /// Validates transaction against the state. -pub fn validate_tx_against_state( - context: &mut Context, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> +pub fn validate_tx_against_state( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> where - ::ValidationError: From, + ::ValidationError: From, { // load acc let tx_caller = context.evm.env.tx.caller(); @@ -49,11 +49,11 @@ where } /// Validate initial transaction gas. -pub fn validate_initial_tx_gas( - env: &Env, -) -> EVMResultGeneric +pub fn validate_initial_tx_gas( + env: &Env, +) -> EVMResultGeneric where - ::ValidationError: From, + ::ValidationError: From, { let input = &env.tx.data(); let is_create = env.tx.kind().is_create(); diff --git a/crates/revm/src/handler/register.rs b/crates/revm/src/handler/register.rs index be300ca999..b151715843 100644 --- a/crates/revm/src/handler/register.rs +++ b/crates/revm/src/handler/register.rs @@ -1,29 +1,29 @@ -use crate::{db::Database, handler::Handler, ChainSpec, Context}; +use crate::{db::Database, handler::Handler, Context, EvmWiring}; use std::boxed::Box; /// EVM Handler -pub type EvmHandler<'a, ChainSpecT, EXT, DB> = - Handler<'a, ChainSpecT, Context, EXT, DB>; +pub type EvmHandler<'a, EvmWiringT, EXT, DB> = + Handler<'a, EvmWiringT, Context, EXT, DB>; // Handle register -pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, ChainSpecT, EXT, DB>); +pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, EvmWiringT, EXT, DB>); // Boxed handle register -pub type HandleRegisterBox<'a, ChainSpecT, EXT, DB> = - Box Fn(&mut EvmHandler<'e, ChainSpecT, EXT, DB>) + 'a>; +pub type HandleRegisterBox<'a, EvmWiringT, EXT, DB> = + Box Fn(&mut EvmHandler<'e, EvmWiringT, EXT, DB>) + 'a>; -pub enum HandleRegisters<'a, ChainSpecT: ChainSpec, EXT, DB: Database> { +pub enum HandleRegisters<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { /// Plain function register - Plain(HandleRegister), + Plain(HandleRegister), /// Boxed function register. - Box(HandleRegisterBox<'a, ChainSpecT, EXT, DB>), + Box(HandleRegisterBox<'a, EvmWiringT, EXT, DB>), } -impl<'register, ChainSpecT: ChainSpec, EXT, DB: Database> - HandleRegisters<'register, ChainSpecT, EXT, DB> +impl<'register, EvmWiringT: EvmWiring, EXT, DB: Database> + HandleRegisters<'register, EvmWiringT, EXT, DB> { /// Call register function to modify EvmHandler. - pub fn register<'evm>(&self, handler: &mut EvmHandler<'evm, ChainSpecT, EXT, DB>) + pub fn register<'evm>(&self, handler: &mut EvmHandler<'evm, EvmWiringT, EXT, DB>) where 'evm: 'register, { diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 55096076a0..2e588af785 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -13,7 +13,7 @@ use crate::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, }, primitives::{db::Database, Address, Log, U256}, - ChainSpec, EvmContext, + EvmContext, EvmWiring, }; use auto_impl::auto_impl; @@ -29,7 +29,7 @@ pub mod inspectors { /// EVM [Interpreter] callbacks. #[auto_impl(&mut, Box)] -pub trait Inspector { +pub trait Inspector { /// Called before the interpreter is initialized. /// /// If `interp.instruction_result` is set to anything other than [crate::interpreter::InstructionResult::Continue] then the execution of the interpreter @@ -38,7 +38,7 @@ pub trait Inspector { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { let _ = interp; let _ = context; @@ -53,7 +53,7 @@ pub trait Inspector { /// /// To get the current opcode, use `interp.current_opcode()`. #[inline] - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let _ = interp; let _ = context; } @@ -63,7 +63,7 @@ pub trait Inspector { /// Setting `interp.instruction_result` to anything other than [crate::interpreter::InstructionResult::Continue] alters the execution /// of the interpreter. #[inline] - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let _ = interp; let _ = context; } @@ -73,7 +73,7 @@ pub trait Inspector { fn log( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, log: &Log, ) { let _ = interp; @@ -87,7 +87,7 @@ pub trait Inspector { #[inline] fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut CallInputs, ) -> Option { let _ = context; @@ -103,7 +103,7 @@ pub trait Inspector { #[inline] fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -120,7 +120,7 @@ pub trait Inspector { #[inline] fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { let _ = context; @@ -135,7 +135,7 @@ pub trait Inspector { #[inline] fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -149,7 +149,7 @@ pub trait Inspector { /// This can happen from create TX or from EOFCREATE opcode. fn eofcreate( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut EOFCreateInputs, ) -> Option { let _ = context; @@ -160,7 +160,7 @@ pub trait Inspector { /// Called when eof creating has ended. fn eofcreate_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &EOFCreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index a23501ffdc..87de94df0a 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -9,7 +9,7 @@ use crate::{ inspectors::GasInspector, interpreter::{CallInputs, CreateInputs, Interpreter}, primitives::{Address, U256}, - ChainSpec, Database, EvmContext, Inspector, + Database, EvmContext, EvmWiring, Inspector, }; /// Custom print [Inspector], it has step level information of execution. @@ -20,18 +20,18 @@ pub struct CustomPrintTracer { gas_inspector: GasInspector, } -impl Inspector for CustomPrintTracer { +impl Inspector for CustomPrintTracer { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { self.gas_inspector.initialize_interp(interp, context); } // 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, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let opcode = interp.current_opcode(); let name = OpCode::name_by_op(opcode); @@ -56,13 +56,13 @@ impl Inspector for CustomPr self.gas_inspector.step(interp, context); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); } fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -71,7 +71,7 @@ impl Inspector for CustomPr fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -80,7 +80,7 @@ impl Inspector for CustomPr fn call( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, inputs: &mut CallInputs, ) -> Option { println!( @@ -97,7 +97,7 @@ impl Inspector for CustomPr fn create( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { println!( diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index ba531c3ce0..550dd94b73 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -4,7 +4,7 @@ use crate::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterResult, }, primitives::{db::Database, hex, HashMap, Transaction, B256, U256}, - ChainSpec, EvmContext, Inspector, + EvmContext, EvmWiring, Inspector, }; use revm_interpreter::OpCode; use serde::Serialize; @@ -162,10 +162,10 @@ impl TracerEip3155 { self.output.flush() } - fn print_summary( + fn print_summary( &mut self, result: &InterpreterResult, - context: &mut EvmContext, + context: &mut EvmContext, ) { if self.print_summary { let spec_name: &str = context.spec_id().into(); @@ -184,16 +184,16 @@ impl TracerEip3155 { } } -impl Inspector for TracerEip3155 { +impl Inspector for TracerEip3155 { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { self.gas_inspector.initialize_interp(interp, context); } - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step(interp, context); self.stack.clone_from(interp.stack.data()); self.memory = if self.include_memory { @@ -208,7 +208,7 @@ impl Inspector for TracerEi self.refunded = interp.gas.refunded(); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); if self.skip { self.skip = false; @@ -241,7 +241,7 @@ impl Inspector for TracerEi fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -258,7 +258,7 @@ impl Inspector for TracerEi fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index dfa5a5c1d0..b886eead9c 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -5,7 +5,7 @@ use revm_interpreter::CallOutcome; use crate::{ interpreter::{CallInputs, CreateInputs, CreateOutcome}, primitives::db::Database, - ChainSpec, EvmContext, Inspector, + EvmContext, EvmWiring, Inspector, }; /// Helper [Inspector] that keeps track of gas. @@ -26,11 +26,11 @@ impl GasInspector { } } -impl Inspector for GasInspector { +impl Inspector for GasInspector { fn initialize_interp( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.gas_remaining = interp.gas.limit(); } @@ -38,7 +38,7 @@ impl Inspector for GasInspe fn step( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.gas_remaining = interp.gas.remaining(); } @@ -46,7 +46,7 @@ impl Inspector for GasInspe fn step_end( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { let remaining = interp.gas.remaining(); self.last_gas_cost = self.gas_remaining.saturating_sub(remaining); @@ -55,7 +55,7 @@ impl Inspector for GasInspe fn call_end( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, _inputs: &CallInputs, mut outcome: CallOutcome, ) -> CallOutcome { @@ -68,7 +68,7 @@ impl Inspector for GasInspe fn create_end( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, _inputs: &CreateInputs, mut outcome: CreateOutcome, ) -> CreateOutcome { @@ -89,7 +89,7 @@ mod tests { primitives::{self, Log}, }; - type TestChainSpec = primitives::EthChainSpec; + type TestEvmWiring = primitives::EthEvmWiring; #[derive(Default, Debug)] struct StackInspector { @@ -98,16 +98,16 @@ mod tests { gas_remaining_steps: Vec<(usize, u64)>, } - impl Inspector for StackInspector { + impl Inspector for StackInspector { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { self.gas_inspector.initialize_interp(interp, context); } - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.pc = interp.program_counter(); self.gas_inspector.step(interp, context); } @@ -115,13 +115,13 @@ mod tests { fn log( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, log: &Log, ) { self.gas_inspector.log(interp, context, log); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); self.gas_remaining_steps .push((self.pc, self.gas_inspector.gas_remaining())); @@ -129,7 +129,7 @@ mod tests { fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, call: &mut CallInputs, ) -> Option { self.gas_inspector.call(context, call) @@ -137,7 +137,7 @@ mod tests { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -146,7 +146,7 @@ mod tests { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, call: &mut CreateInputs, ) -> Option { self.gas_inspector.create(context, call); @@ -155,7 +155,7 @@ mod tests { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -191,11 +191,11 @@ mod tests { let bytecode = Bytecode::new_raw(contract_data); let mut evm = Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { - *tx = ::Transaction::default(); + *tx = ::Transaction::default(); tx.caller = address!("1000000000000000000000000000000000000000"); tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 1729bb6aa0..8eab568fbb 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -3,23 +3,23 @@ use crate::{ handler::register::EvmHandler, interpreter::{opcode, InstructionResult, Interpreter}, primitives::EVMResultGeneric, - ChainSpec, Context, FrameOrResult, FrameResult, Inspector, JournalEntry, + Context, EvmWiring, FrameOrResult, FrameResult, Inspector, JournalEntry, }; use core::cell::RefCell; use revm_interpreter::opcode::DynInstruction; use std::{rc::Rc, sync::Arc, vec::Vec}; /// Provides access to an `Inspector` instance. -pub trait GetInspector { +pub trait GetInspector { /// Returns the associated `Inspector`. - fn get_inspector(&mut self) -> &mut impl Inspector; + fn get_inspector(&mut self) -> &mut impl Inspector; } -impl> - GetInspector for INSP +impl> + GetInspector for INSP { #[inline] - fn get_inspector(&mut self) -> &mut impl Inspector { + fn get_inspector(&mut self) -> &mut impl Inspector { self } } @@ -37,11 +37,11 @@ impl> /// and in case of Logs and Selfdestruct wrapper is wrapped again for the /// `log` and `selfdestruct` calls. pub fn inspector_handle_register< - ChainSpecT: ChainSpec, + EvmWiringT: EvmWiring, DB: Database, - EXT: GetInspector, + EXT: GetInspector, >( - handler: &mut EvmHandler<'_, ChainSpecT, EXT, DB>, + handler: &mut EvmHandler<'_, EvmWiringT, EXT, DB>, ) { let table = &mut handler.instruction_table; @@ -96,7 +96,7 @@ pub fn inspector_handle_register< let create_input_stack_inner = create_input_stack.clone(); let prev_handle = handler.execution.create.clone(); handler.execution.create = Arc::new( - move |ctx, mut inputs| -> EVMResultGeneric { + move |ctx, mut inputs| -> EVMResultGeneric { let inspector = ctx.external.get_inspector(); // call inspector create to change input or return outcome. if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { @@ -223,13 +223,13 @@ pub fn inspector_handle_register< }); } -fn inspector_instruction( - prev: &DynInstruction<'_, Context>, +fn inspector_instruction( + prev: &DynInstruction<'_, Context>, interpreter: &mut Interpreter, - host: &mut Context, + host: &mut Context, ) where - ChainSpecT: ChainSpec, - INSP: GetInspector, + EvmWiringT: EvmWiring, + INSP: GetInspector, DB: Database, { // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the @@ -265,7 +265,7 @@ mod tests { primitives, Evm, EvmContext, }; - type TestChainSpec = primitives::EthChainSpec; + type TestEvmWiring = primitives::EthEvmWiring; #[derive(Default, Debug)] struct StackInspector { @@ -276,11 +276,11 @@ mod tests { call_end: bool, } - impl Inspector for StackInspector { + impl Inspector for StackInspector { fn initialize_interp( &mut self, _interp: &mut Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { if self.initialize_interp_called { unreachable!("initialize_interp should not be called twice") @@ -288,21 +288,21 @@ mod tests { self.initialize_interp_called = true; } - fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { self.step += 1; } fn step_end( &mut self, _interp: &mut Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.step_end += 1; } fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _call: &mut CallInputs, ) -> Option { if self.call { @@ -315,7 +315,7 @@ mod tests { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -329,7 +329,7 @@ mod tests { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _call: &mut CreateInputs, ) -> Option { assert_eq!(context.journaled_state.depth(), 0); @@ -338,7 +338,7 @@ mod tests { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -374,11 +374,11 @@ mod tests { let bytecode = Bytecode::new_raw(contract_data); let mut evm = Evm::builder() - .with_chain_spec::() + .with_chain_spec::() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { - *tx = ::Transaction::default(); + *tx = ::Transaction::default(); tx.caller = address!("1000000000000000000000000000000000000000"); tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); diff --git a/crates/revm/src/inspector/noop.rs b/crates/revm/src/inspector/noop.rs index 412356178c..5395109d26 100644 --- a/crates/revm/src/inspector/noop.rs +++ b/crates/revm/src/inspector/noop.rs @@ -1,7 +1,7 @@ -use crate::{ChainSpec, Database, Inspector}; +use crate::{Database, EvmWiring, Inspector}; /// Dummy [Inspector], helpful as standalone replacement. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoOpInspector; -impl Inspector for NoOpInspector {} +impl Inspector for NoOpInspector {} diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 1896be4eb5..061d568932 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -27,11 +27,11 @@ pub mod optimism; // Export items. pub use builder::EvmBuilder; -pub use chain_spec::ChainSpec; +pub use chain_spec::EvmWiring; pub use context::{ Context, ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, - ContextWithChainSpec, EvmContext, InnerEvmContext, + ContextWithEvmWiring, EvmContext, InnerEvmContext, }; pub use db::{ CacheState, DBBox, State, StateBuilder, StateDBBox, TransitionAccount, TransitionState, diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index 6445ef0683..863c19805d 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -53,8 +53,8 @@ pub trait OptimismTransaction { } /// Trait for an Optimism chain spec. -pub trait OptimismChainSpec: - crate::ChainSpec< +pub trait OptimismEvmWiring: + crate::EvmWiring< Context: OptimismContext, Hardfork = OptimismSpecId, HaltReason = OptimismHaltReason, @@ -64,8 +64,8 @@ pub trait OptimismChainSpec: { } -impl OptimismChainSpec for ChainSpecT where - ChainSpecT: crate::ChainSpec< +impl OptimismEvmWiring for EvmWiringT where + EvmWiringT: crate::EvmWiring< Context: OptimismContext, Hardfork = OptimismSpecId, HaltReason = OptimismHaltReason, diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index af5568cad3..42f794c8d3 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -19,43 +19,43 @@ use std::string::ToString; use std::sync::Arc; use super::{ - OptimismChainSpec, OptimismContext, OptimismHaltReason, OptimismInvalidTransaction, + OptimismContext, OptimismEvmWiring, OptimismHaltReason, OptimismInvalidTransaction, OptimismSpec, OptimismSpecId, OptimismTransaction as _, }; -pub fn optimism_handle_register( - handler: &mut EvmHandler<'_, ChainSpecT, EXT, DB>, +pub fn optimism_handle_register( + handler: &mut EvmHandler<'_, EvmWiringT, EXT, DB>, ) where - ChainSpecT: OptimismChainSpec, + EvmWiringT: OptimismEvmWiring, DB: Database, { optimism_spec_to_generic!(handler.spec_id, { // validate environment - handler.validation.env = Arc::new(validate_env::); + handler.validation.env = Arc::new(validate_env::); // Validate transaction against state. handler.validation.tx_against_state = - Arc::new(validate_tx_against_state::); + Arc::new(validate_tx_against_state::); // Load additional precompiles for the given chain spec. handler.pre_execution.load_precompiles = - Arc::new(load_precompiles::); + Arc::new(load_precompiles::); // load l1 data - handler.pre_execution.load_accounts = Arc::new(load_accounts::); + handler.pre_execution.load_accounts = Arc::new(load_accounts::); // An estimated batch cost is charged from the caller and added to L1 Fee Vault. - handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); + handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); // Refund is calculated differently then mainnet. handler.execution.last_frame_return = - Arc::new(last_frame_return::); + Arc::new(last_frame_return::); handler.post_execution.reward_beneficiary = - Arc::new(reward_beneficiary::); + Arc::new(reward_beneficiary::); // In case of halt of deposit transaction return Error. - handler.post_execution.output = Arc::new(output::); - handler.post_execution.end = Arc::new(end::); + handler.post_execution.output = Arc::new(output::); + handler.post_execution.end = Arc::new(end::); }); } /// Validate environment for the Optimism chain. -pub fn validate_env( - env: &Env, +pub fn validate_env( + env: &Env, ) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. if env.tx.source_hash().is_some() { @@ -80,23 +80,23 @@ pub fn validate_env( - context: &mut Context, + context: &mut Context, ) -> Result<(), EVMError> { if context.evm.inner.env.tx.source_hash().is_some() { return Ok(()); } - mainnet::validate_tx_against_state::(context) + mainnet::validate_tx_against_state::(context) } /// Handle output of the transaction #[inline] -pub fn last_frame_return( - context: &mut Context, +pub fn last_frame_return( + context: &mut Context, frame_result: &mut FrameResult, ) -> Result<(), EVMError> { let env = context.evm.inner.env(); @@ -167,8 +167,8 @@ pub fn last_frame_return( -) -> ContextPrecompiles { +pub fn load_precompiles( +) -> ContextPrecompiles { let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)); if SPEC::optimism_enabled(OptimismSpecId::FJORD) { @@ -183,9 +183,9 @@ pub fn load_precompiles( - context: &mut Context, -) -> EVMResultGeneric<(), ChainSpecT, DB::Error> { +fn load_accounts( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { // the L1-cost fee is only computed for Optimism non-deposit transactions. if context.evm.env.tx.source_hash().is_none() { @@ -197,13 +197,13 @@ fn load_accounts(context) + mainnet::load_accounts::(context) } /// Deduct max balance from caller #[inline] -pub fn deduct_caller( - context: &mut Context, +pub fn deduct_caller( + context: &mut Context, ) -> Result<(), EVMError> { // load caller's account. let (caller_account, _) = context @@ -225,7 +225,7 @@ pub fn deduct_caller(caller_account, &context.evm.inner.env); + deduct_caller_inner::(caller_account, &context.evm.inner.env); // If the transaction is not a deposit transaction, subtract the L1 data fee from the // caller's balance directly after minting the requested amount of ETH. @@ -259,15 +259,15 @@ pub fn deduct_caller( - context: &mut Context, +pub fn reward_beneficiary( + context: &mut Context, gas: &Gas, ) -> Result<(), EVMError> { let is_deposit = context.evm.inner.env.tx.source_hash().is_some(); // transfer fee to coinbase/beneficiary. if !is_deposit { - mainnet::reward_beneficiary::(context, gas)?; + mainnet::reward_beneficiary::(context, gas)?; } if !is_deposit { @@ -318,11 +318,11 @@ pub fn reward_beneficiary( - context: &mut Context, +pub fn output( + context: &mut Context, frame_result: FrameResult, -) -> Result, EVMError> { - let result = mainnet::output::(context, frame_result)?; +) -> Result, EVMError> { + let result = mainnet::output::(context, frame_result)?; if result.result.is_halt() { // Post-regolith, if the transaction is a deposit transaction and it halts, @@ -340,10 +340,10 @@ pub fn output( - context: &mut Context, - evm_output: Result, EVMError>, -) -> Result, EVMError> { +pub fn end( + context: &mut Context, + evm_output: Result, EVMError>, +) -> Result, EVMError> { evm_output.or_else(|err| { if matches!(err, EVMError::Transaction(_)) && context.evm.inner.env().tx.source_hash().is_some() @@ -419,7 +419,7 @@ mod tests { /// Creates frame result. fn call_last_frame_return( - env: Env, + env: Env, instruction_result: InstructionResult, gas: Gas, ) -> Gas @@ -436,13 +436,13 @@ mod tests { }, 0..0, )); - last_frame_return::(&mut ctx, &mut first_frame).unwrap(); + last_frame_return::(&mut ctx, &mut first_frame).unwrap(); *first_frame.gas() } #[test] fn test_revert_gas() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = None; @@ -455,7 +455,7 @@ mod tests { #[test] fn test_consume_gas() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -468,7 +468,7 @@ mod tests { #[test] fn test_consume_gas_with_refund() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -489,7 +489,7 @@ mod tests { #[test] fn test_consume_gas_sys_deposit_tx() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -511,7 +511,7 @@ mod tests { }, ); - let mut context: Context = Context::new_with_db(db); + let mut context: Context = Context::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -523,7 +523,7 @@ mod tests { // added mint value is 10. context.evm.inner.env.tx.mint = Some(10); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let (account, _) = context @@ -546,7 +546,7 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); + let mut context: Context = Context::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -561,7 +561,7 @@ mod tests { // so enveloped_tx gas cost is ignored. context.evm.inner.env.tx.source_hash = Some(B256::ZERO); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let (account, _) = context @@ -584,7 +584,7 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); + let mut context: Context = Context::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -593,7 +593,7 @@ mod tests { }); // l1block cost is 1048 fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let (account, _) = context @@ -616,7 +616,7 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); + let mut context: Context = Context::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -627,7 +627,7 @@ mod tests { context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); assert_eq!( - deduct_caller::(&mut context), + deduct_caller::(&mut context), Err(EVMError::Transaction( InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(U256::from(1048)), @@ -641,34 +641,34 @@ mod tests { #[test] fn test_validate_sys_tx() { // mark the tx as a system transaction. - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.is_system_transaction = Some(true); assert_eq!( - validate_env::(&env), + validate_env::(&env), Err(EVMError::Transaction( OptimismInvalidTransaction::DepositSystemTxPostRegolith )) ); // Pre-regolith system transactions should be allowed. - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_deposit_tx() { // Set source hash. - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.source_hash = Some(B256::ZERO); - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_tx_against_state_deposit_tx() { // Set source hash. - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.source_hash = Some(B256::ZERO); // Nonce and balance checks should be skipped for deposit transactions. - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } } diff --git a/crates/revm/src/optimism/spec.rs b/crates/revm/src/optimism/spec.rs index 4698ec37f9..2ee9a97354 100644 --- a/crates/revm/src/optimism/spec.rs +++ b/crates/revm/src/optimism/spec.rs @@ -9,16 +9,16 @@ use crate::{ use super::{env::TxEnv, OptimismContext, OptimismHaltReason}; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ChainSpec; +pub struct EvmWiring; -impl crate::primitives::ChainSpec for ChainSpec { +impl crate::primitives::EvmWiring for EvmWiring { type Block = BlockEnv; type Hardfork = OptimismSpecId; type HaltReason = OptimismHaltReason; type Transaction = TxEnv; } -impl crate::ChainSpec for ChainSpec { +impl crate::EvmWiring for EvmWiring { type Context = Context; fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> diff --git a/examples/db_by_ref.rs b/examples/db_by_ref.rs index d866899d71..037399a756 100644 --- a/examples/db_by_ref.rs +++ b/examples/db_by_ref.rs @@ -3,7 +3,7 @@ use revm::{ handler::register::HandleRegister, inspector_handle_register, inspectors::{NoOpInspector, TracerEip3155}, - primitives::{EthChainSpec, ResultAndState}, + primitives::{EthEvmWiring, ResultAndState}, DatabaseCommit, DatabaseRef, Evm, }; use std::error::Error; @@ -23,8 +23,8 @@ where fn run_transaction( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, -) -> anyhow::Result<(ResultAndState, DB)> { + register_handles_fn: HandleRegister>, +) -> anyhow::Result<(ResultAndState, DB)> { let mut evm = Evm::builder() .with_ref_db(db) .with_external_context(ext) @@ -38,7 +38,7 @@ fn run_transaction( fn run_transaction_and_commit_with_ext( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, + register_handles_fn: HandleRegister>, ) -> anyhow::Result<()> { // To circumvent borrow checker issues, we need to move the database into the // transaction and return it after the transaction is done. From 57a3febec8ee859c1964b6b1b6a1d9f11294e32b Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 13:03:34 +0200 Subject: [PATCH 29/59] chore: clippy comments fix --- crates/precompile/src/bls12_381/pairing.rs | 2 ++ crates/precompile/src/bls12_381/utils.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index e0c50dd834..603a5bea22 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -26,10 +26,12 @@ const INPUT_LENGTH: usize = 384; /// following structure: /// * 128 bytes of G1 point encoding /// * 256 bytes of G2 point encoding +/// /// Each point is expected to be in the subgroup of order q. /// Output is 32 bytes where first 31 bytes are equal to 0x00 and the last byte /// is 0x01 if pairing result is equal to the multiplicative identity in a pairing /// target field and 0x00 otherwise. +/// /// See also: pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_len = input.len(); diff --git a/crates/precompile/src/bls12_381/utils.rs b/crates/precompile/src/bls12_381/utils.rs index a2ed3cd885..b576fcc53f 100644 --- a/crates/precompile/src/bls12_381/utils.rs +++ b/crates/precompile/src/bls12_381/utils.rs @@ -56,11 +56,11 @@ pub(super) fn remove_padding(input: &[u8]) -> Result<&[u8; FP_LENGTH], Precompil /// /// From [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537): /// * A scalar for the multiplication operation is encoded as 32 bytes by performing BigEndian -/// encoding of the corresponding (unsigned) integer. +/// encoding of the corresponding (unsigned) integer. /// /// We do not check that the scalar is a canonical Fr element, because the EIP specifies: /// * The corresponding integer is not required to be less than or equal than main subgroup order -/// `q`. +/// `q`. pub(super) fn extract_scalar_input(input: &[u8]) -> Result { if input.len() != SCALAR_LENGTH { return Err(PrecompileError::Other(format!( From b6e90b6ea36766069bb30431326ca1e7ccc022fc Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 13:56:22 +0200 Subject: [PATCH 30/59] chore: rename EthEvmWiring to EthereumWiring --- bins/revme/src/cmd/statetest/runner.rs | 2 +- crates/interpreter/src/host.rs | 6 ++--- .../interpreter/src/instructions/bitwise.rs | 10 ++++---- .../interpreter/src/instructions/control.rs | 18 +++++++------- crates/interpreter/src/instructions/data.rs | 6 ++--- crates/interpreter/src/instructions/stack.rs | 8 +++---- crates/interpreter/src/instructions/system.rs | 6 ++--- crates/interpreter/src/interpreter.rs | 20 +++++++++------- crates/precompile/src/bls12_381/pairing.rs | 4 ++-- crates/primitives/src/chain_spec.rs | 4 ++-- crates/primitives/src/env.rs | 6 ++--- crates/revm/benches/bench.rs | 8 +++---- crates/revm/src/builder.rs | 14 +++++------ crates/revm/src/chain_spec.rs | 4 ++-- crates/revm/src/context.rs | 4 ++-- .../revm/src/context/context_precompiles.rs | 4 ++-- crates/revm/src/context/evm_context.rs | 10 ++++---- crates/revm/src/evm.rs | 6 ++--- crates/revm/src/handler.rs | 2 +- crates/revm/src/handler/mainnet/execution.rs | 6 ++--- crates/revm/src/inspector/gas.rs | 2 +- crates/revm/src/inspector/handler_register.rs | 2 +- crates/revm/src/optimism.rs | 4 ++-- crates/revm/src/optimism/handler_register.rs | 24 +++++++++---------- examples/db_by_ref.rs | 8 +++---- 25 files changed, 95 insertions(+), 93 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index f1d5fbccc3..072dafc682 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -28,7 +28,7 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; -type TestEvmWiring = revm::primitives::EthEvmWiring; +type TestEvmWiring = revm::primitives::EthereumWiring; #[derive(Debug, Error)] #[error("Test {name} failed: {kind}")] diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index c9563a826a..f438638bce 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -88,7 +88,7 @@ pub struct SelfDestructResult { #[cfg(test)] mod tests { - use revm_primitives::EthEvmWiring; + use revm_primitives::EthereumWiring; use super::*; @@ -96,7 +96,7 @@ mod tests { #[test] fn object_safety() { - assert_host::>(); - assert_host::>(); + assert_host::>(); + assert_host::>(); } } diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index d156c3ce33..e10c2987ca 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -125,7 +125,7 @@ pub fn sar(interpreter: &mut Interpreter, _host: & mod tests { use crate::instructions::bitwise::{byte, sar, shl, shr}; use crate::{Contract, DummyHost, Interpreter}; - use revm_primitives::{uint, Env, EthEvmWiring, LatestSpec, U256}; + use revm_primitives::{uint, Env, EthereumWiring, LatestSpec, U256}; #[test] fn test_shift_left() { @@ -202,7 +202,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shl::, LatestSpec>(&mut interpreter, &mut host); + shl::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -283,7 +283,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shr::, LatestSpec>(&mut interpreter, &mut host); + shr::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -389,7 +389,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - sar::, LatestSpec>(&mut interpreter, &mut host); + sar::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -403,7 +403,7 @@ mod tests { expected: U256, } - let mut host = DummyHost::new(Env::::default()); + let mut host = DummyHost::new(Env::::default()); let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index a9e081d871..a3ec57c91c 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -206,7 +206,7 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { mod test { use std::sync::Arc; - use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, EthEvmWiring, PragueSpec}; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, EthereumWiring, PragueSpec}; use super::*; use crate::{ @@ -216,7 +216,7 @@ mod test { #[test] fn rjump() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMP, 0x00, 0x02, STOP, STOP, @@ -230,7 +230,7 @@ mod test { #[test] fn rjumpi() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP, @@ -250,7 +250,7 @@ mod test { #[test] fn rjumpv() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPV, @@ -332,7 +332,7 @@ mod test { #[test] fn callf_retf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]); let bytes2 = Bytes::from([RETF]); @@ -363,7 +363,7 @@ mod test { #[test] fn callf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -387,7 +387,7 @@ mod test { #[test] fn callf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -404,7 +404,7 @@ mod test { #[test] fn jumpf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -425,7 +425,7 @@ mod test { #[test] fn jumpf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index 99f031c8b1..180c11054b 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -83,7 +83,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { - use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, EthEvmWiring, PragueSpec}; + use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, EthereumWiring, PragueSpec}; use std::sync::Arc; use super::*; @@ -107,7 +107,7 @@ mod test { #[test] fn dataload_dataloadn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([ DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN, @@ -163,7 +163,7 @@ mod test { #[test] fn data_copy() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY])); diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index dde28b61ee..99894658ed 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -89,13 +89,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, DUPN, EXCHANGE, SWAPN}, - primitives::{Bytecode, Bytes, EthEvmWiring, PragueSpec}, + primitives::{Bytecode, Bytes, EthereumWiring, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn dupn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ DUPN, 0x00, DUPN, 0x01, DUPN, 0x02, @@ -115,7 +115,7 @@ mod test { #[test] fn swapn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([SWAPN, 0x00, SWAPN, 0x01]))); @@ -135,7 +135,7 @@ mod test { #[test] fn exchange() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ EXCHANGE, 0x00, EXCHANGE, 0x11, diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 8d7ac22a3b..f30d0cc397 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -189,13 +189,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, RETURNDATACOPY, RETURNDATALOAD}, - primitives::{bytes, Bytecode, EthEvmWiring, PragueSpec}, + primitives::{bytes, Bytecode, EthereumWiring, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn returndataload() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( @@ -254,7 +254,7 @@ mod test { #[test] fn returndatacopy() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( [ diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 935f62fbe3..0aacbe170c 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -469,22 +469,24 @@ pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) mod tests { use super::*; use crate::{opcode::InstructionTable, DummyHost}; - use revm_primitives::{CancunSpec, EthEvmWiring}; + use revm_primitives::{CancunSpec, EthereumWiring}; #[test] fn object_safety() { let mut interp = Interpreter::new(Contract::default(), u64::MAX, false); - let mut host = crate::DummyHost::::default(); - let table: &InstructionTable> = - &crate::opcode::make_instruction_table::, CancunSpec>(); + let mut host = crate::DummyHost::::default(); + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::, CancunSpec>(); let _ = interp.run(EMPTY_SHARED_MEMORY, table, &mut host); - let host: &mut dyn Host = - &mut host as &mut dyn Host; - let table: &InstructionTable> = - &crate::opcode::make_instruction_table::, CancunSpec>( - ); + let host: &mut dyn Host = + &mut host as &mut dyn Host; + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::< + dyn Host, + CancunSpec, + >(); let _ = interp.run(EMPTY_SHARED_MEMORY, table, host); } } diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index 603a5bea22..a786a8b7dc 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -26,12 +26,12 @@ const INPUT_LENGTH: usize = 384; /// following structure: /// * 128 bytes of G1 point encoding /// * 256 bytes of G2 point encoding -/// +/// /// Each point is expected to be in the subgroup of order q. /// Output is 32 bytes where first 31 bytes are equal to 0x00 and the last byte /// is 0x01 if pairing result is equal to the multiplicative identity in a pairing /// target field and 0x00 otherwise. -/// +/// /// See also: pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_len = input.len(); diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 1387f06f0e..0d9164c90e 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -47,9 +47,9 @@ pub trait EvmWiring: Sized + 'static { } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct EthEvmWiring; +pub struct EthereumWiring; -impl EvmWiring for EthEvmWiring { +impl EvmWiring for EthereumWiring { type Block = crate::BlockEnv; type Hardfork = SpecId; type HaltReason = crate::HaltReason; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 736bb51716..11c9292da2 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -767,13 +767,13 @@ pub enum AnalysisKind { #[cfg(test)] mod tests { - use crate::EthEvmWiring; + use crate::EthereumWiring; use super::*; #[test] fn test_validate_tx_chain_id() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.chain_id = Some(1); env.cfg.chain_id = 2; assert_eq!( @@ -784,7 +784,7 @@ mod tests { #[test] fn test_validate_tx_access_list() { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.access_list = vec![AccessListItem { address: Address::ZERO, storage_keys: vec![], diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index 8c42e79433..0c0cdcb682 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -4,7 +4,7 @@ use criterion::{ use revm::{ db::BenchmarkDB, interpreter::{analysis::to_analysed, Contract, DummyHost, Interpreter}, - primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, EthEvmWiring, TxKind, U256}, + primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, EthereumWiring, TxKind, U256}, Evm, }; use revm_interpreter::{opcode::make_instruction_table, SharedMemory, EMPTY_SHARED_MEMORY}; @@ -83,7 +83,7 @@ fn transfer(c: &mut Criterion) { fn bench_transact( g: &mut BenchmarkGroup<'_, WallTime>, - evm: &mut Evm<'_, EthEvmWiring, EXT, BenchmarkDB>, + evm: &mut Evm<'_, EthereumWiring, EXT, BenchmarkDB>, ) { let state = match evm.context.evm.db.0 { Bytecode::LegacyRaw(_) => "raw", @@ -96,7 +96,7 @@ fn bench_transact( fn bench_eval( g: &mut BenchmarkGroup<'_, WallTime>, - evm: &mut Evm<'static, EthEvmWiring, (), BenchmarkDB>, + evm: &mut Evm<'static, EthereumWiring, (), BenchmarkDB>, ) { g.bench_function("eval", |b| { let contract = Contract { @@ -106,7 +106,7 @@ fn bench_eval( }; let mut shared_memory = SharedMemory::new(); let mut host = DummyHost::new(*evm.context.evm.env.clone()); - let instruction_table = make_instruction_table::, BerlinSpec>(); + let instruction_table = make_instruction_table::, BerlinSpec>(); b.iter(move || { // replace memory with empty memory to use it inside interpreter. // Later return memory back. diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 8207a7dfee..bf381abebd 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,7 +1,7 @@ use crate::{ db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, handler::{register, CfgEnvWithEvmWiring, EnvWithEvmWiring}, - primitives::{self, CfgEnv, Env, EthEvmWiring, InvalidTransaction, TransactionValidation}, + primitives::{self, CfgEnv, Env, EthereumWiring, InvalidTransaction, TransactionValidation}, Context, ContextWithEvmWiring, Evm, EvmContext, EvmWiring, Handler, }; use core::marker::PhantomData; @@ -26,12 +26,12 @@ pub struct SetGenericStage; /// Requires the database and external context to be set. pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthEvmWiring, (), EmptyDB> { +impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring, (), EmptyDB> { fn default() -> Self { Self { context: Context::default(), - handler: EthEvmWiring::handler::<'a, (), EmptyDB>( - ::Hardfork::default(), + handler: EthereumWiring::handler::<'a, (), EmptyDB>( + ::Hardfork::default(), ), phantom: PhantomData, } @@ -243,12 +243,12 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> /// /// # Example /// ```rust - /// use revm::{EvmBuilder, EvmHandler, db::EmptyDB, primitives::{EthEvmWiring, SpecId}}; + /// use revm::{EvmBuilder, EvmHandler, db::EmptyDB, primitives::{EthereumWiring, SpecId}}; /// use revm_interpreter::primitives::CancunSpec; /// let builder = EvmBuilder::default(); /// /// // get the desired handler - /// let mainnet = EvmHandler::<'_, EthEvmWiring, (), EmptyDB>::mainnet_with_spec(SpecId::CANCUN); + /// let mainnet = EvmHandler::<'_, EthereumWiring, (), EmptyDB>::mainnet_with_spec(SpecId::CANCUN); /// let builder = builder.with_handler(mainnet); /// /// // build the EVM @@ -442,7 +442,7 @@ mod test { use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; - type TestEvmWiring = crate::primitives::EthEvmWiring; + type TestEvmWiring = crate::primitives::EthereumWiring; /// Custom evm context #[derive(Default, Clone, Debug)] diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index d079bb1990..418a139ef1 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -1,7 +1,7 @@ use crate::{ handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, interpreter::opcode::InstructionTables, - primitives::{db::Database, spec_to_generic, EthEvmWiring}, + primitives::{db::Database, spec_to_generic, EthereumWiring}, EvmHandler, }; use std::vec::Vec; @@ -16,7 +16,7 @@ pub trait EvmWiring: crate::primitives::EvmWiring { DB: Database; } -impl EvmWiring for EthEvmWiring { +impl EvmWiring for EthereumWiring { type Context = (); fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 88f7320f9a..eeac20e9ae 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -15,7 +15,7 @@ use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, primitives::{ - Address, Block as _, Bytes, Env, EthEvmWiring, Log, B256, BLOCK_HASH_HISTORY, U256, + Address, Block as _, Bytes, Env, EthereumWiring, Log, B256, BLOCK_HASH_HISTORY, U256, }, EvmWiring, }; @@ -30,7 +30,7 @@ pub struct Context { pub external: EXT, } -impl Default for Context { +impl Default for Context { fn default() -> Self { Self::new_empty() } diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index 6ecee9b8e8..ac96105ff3 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -228,14 +228,14 @@ impl From for ContextPrecompile #[cfg(test)] mod tests { use super::*; - use crate::{db::EmptyDB, primitives::EthEvmWiring}; + use crate::{db::EmptyDB, primitives::EthereumWiring}; #[test] fn test_precompiles_context() { let custom_address = Address::with_last_byte(0xff); let mut precompiles = - ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); + ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); assert_eq!(precompiles.addresses().count(), 4); assert!(matches!(precompiles.inner, PrecompilesCow::StaticRef(_))); assert!(!precompiles.contains(&custom_address)); diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index bde0e7cc10..7f5b8c7111 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -539,7 +539,7 @@ mod tests { use crate::primitives::U256; use crate::{ db::{CacheDB, EmptyDB}, - primitives::{address, Bytecode, EthEvmWiring}, + primitives::{address, Bytecode, EthereumWiring}, Frame, JournalEntry, }; use std::boxed::Box; @@ -549,7 +549,7 @@ mod tests { // call stack is too deep. #[test] fn test_make_call_frame_stack_too_deep() { - let env = Env::::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut context = test_utils::create_empty_evm_context(Box::new(env), db); context.journaled_state.depth = CALL_STACK_LIMIT as usize + 1; @@ -570,7 +570,7 @@ mod tests { // checkpointed on the journaled state correctly. #[test] fn test_make_call_frame_transfer_revert() { - let env = Env::::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut evm_context = test_utils::create_empty_evm_context(Box::new(env), db); let contract = address!("dead10000000000000000000000000000001dead"); @@ -591,7 +591,7 @@ mod tests { #[test] fn test_make_call_frame_missing_code_context() { - let env = Env::::default(); + let env = Env::::default(); let cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let mut context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); @@ -606,7 +606,7 @@ mod tests { #[test] fn test_make_call_frame_succeeds() { - let env = Env::::default(); + let env = Env::::default(); let mut cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let by = Bytecode::new_raw(Bytes::from(vec![0x60, 0x00, 0x60, 0x00])); diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 8228635eb4..1dc9dcaedd 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,7 +6,7 @@ use crate::{ handler::{EnvWithEvmWiring, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthEvmWiring, ExecutionResult, + CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthereumWiring, ExecutionResult, ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithEvmWiring, EvmWiring, Frame, FrameOrResult, FrameResult, @@ -51,9 +51,9 @@ impl Evm<'_, EvmWirin } } -impl<'a> Evm<'a, EthEvmWiring, (), EmptyDB> { +impl<'a> Evm<'a, EthereumWiring, (), EmptyDB> { /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. - pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthEvmWiring, (), EmptyDB> { + pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthereumWiring, (), EmptyDB> { EvmBuilder::default() } } diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index acca12cc8f..12e2a244c5 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -201,7 +201,7 @@ mod test { #[cfg(feature = "optimism")] type TestEvmWiring = crate::optimism::EvmWiring; #[cfg(not(feature = "optimism"))] - type TestEvmWiring = primitives::EthEvmWiring; + type TestEvmWiring = primitives::EthereumWiring; #[test] fn test_handler_register_pop() { diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 0b3c4dcb42..1a2c044fdd 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -212,13 +212,13 @@ pub fn insert_eofcreate_outcome( #[cfg(test)] mod tests { use super::*; - use crate::primitives::EthEvmWiring; + use crate::primitives::EthereumWiring; use revm_interpreter::primitives::CancunSpec; use revm_precompile::Bytes; /// Creates frame result. fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.gas_limit = 100; let mut first_frame = FrameResult::Call(CallOutcome::new( @@ -229,7 +229,7 @@ mod tests { }, 0..0, )); - frame_return_with_refund_flag::(&env, &mut first_frame, true); + frame_return_with_refund_flag::(&env, &mut first_frame, true); *first_frame.gas() } diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index b886eead9c..4468c817ad 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -89,7 +89,7 @@ mod tests { primitives::{self, Log}, }; - type TestEvmWiring = primitives::EthEvmWiring; + type TestEvmWiring = primitives::EthereumWiring; #[derive(Default, Debug)] struct StackInspector { diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 8eab568fbb..ec9883029c 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -265,7 +265,7 @@ mod tests { primitives, Evm, EvmContext, }; - type TestEvmWiring = primitives::EthEvmWiring; + type TestEvmWiring = primitives::EthereumWiring; #[derive(Default, Debug)] struct StackInspector { diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index 863c19805d..da4388323c 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -53,7 +53,7 @@ pub trait OptimismTransaction { } /// Trait for an Optimism chain spec. -pub trait OptimismEvmWiring: +pub trait OptimismWiring: crate::EvmWiring< Context: OptimismContext, Hardfork = OptimismSpecId, @@ -64,7 +64,7 @@ pub trait OptimismEvmWiring: { } -impl OptimismEvmWiring for EvmWiringT where +impl OptimismWiring for EvmWiringT where EvmWiringT: crate::EvmWiring< Context: OptimismContext, Hardfork = OptimismSpecId, diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 42f794c8d3..3a0b6218b7 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -19,14 +19,14 @@ use std::string::ToString; use std::sync::Arc; use super::{ - OptimismContext, OptimismEvmWiring, OptimismHaltReason, OptimismInvalidTransaction, - OptimismSpec, OptimismSpecId, OptimismTransaction as _, + OptimismContext, OptimismHaltReason, OptimismInvalidTransaction, OptimismSpec, OptimismSpecId, + OptimismTransaction as _, OptimismWiring, }; pub fn optimism_handle_register( handler: &mut EvmHandler<'_, EvmWiringT, EXT, DB>, ) where - EvmWiringT: OptimismEvmWiring, + EvmWiringT: OptimismWiring, DB: Database, { optimism_spec_to_generic!(handler.spec_id, { @@ -54,7 +54,7 @@ pub fn optimism_handle_register( } /// Validate environment for the Optimism chain. -pub fn validate_env( +pub fn validate_env( env: &Env, ) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. @@ -80,7 +80,7 @@ pub fn validate_env( +pub fn last_frame_return( context: &mut Context, frame_result: &mut FrameResult, ) -> Result<(), EVMError> { @@ -167,7 +167,7 @@ pub fn last_frame_return( +pub fn load_precompiles( ) -> ContextPrecompiles { let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)); @@ -183,7 +183,7 @@ pub fn load_precompiles( +fn load_accounts( context: &mut Context, ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { // the L1-cost fee is only computed for Optimism non-deposit transactions. @@ -202,7 +202,7 @@ fn load_accounts( +pub fn deduct_caller( context: &mut Context, ) -> Result<(), EVMError> { // load caller's account. @@ -259,7 +259,7 @@ pub fn deduct_caller( +pub fn reward_beneficiary( context: &mut Context, gas: &Gas, ) -> Result<(), EVMError> { @@ -318,7 +318,7 @@ pub fn reward_beneficiary( +pub fn output( context: &mut Context, frame_result: FrameResult, ) -> Result, EVMError> { @@ -340,7 +340,7 @@ pub fn output( +pub fn end( context: &mut Context, evm_output: Result, EVMError>, ) -> Result, EVMError> { diff --git a/examples/db_by_ref.rs b/examples/db_by_ref.rs index 037399a756..76f50ab8de 100644 --- a/examples/db_by_ref.rs +++ b/examples/db_by_ref.rs @@ -3,7 +3,7 @@ use revm::{ handler::register::HandleRegister, inspector_handle_register, inspectors::{NoOpInspector, TracerEip3155}, - primitives::{EthEvmWiring, ResultAndState}, + primitives::{EthereumWiring, ResultAndState}, DatabaseCommit, DatabaseRef, Evm, }; use std::error::Error; @@ -23,8 +23,8 @@ where fn run_transaction( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, -) -> anyhow::Result<(ResultAndState, DB)> { + register_handles_fn: HandleRegister>, +) -> anyhow::Result<(ResultAndState, DB)> { let mut evm = Evm::builder() .with_ref_db(db) .with_external_context(ext) @@ -38,7 +38,7 @@ fn run_transaction( fn run_transaction_and_commit_with_ext( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, + register_handles_fn: HandleRegister>, ) -> anyhow::Result<()> { // To circumvent borrow checker issues, we need to move the database into the // transaction and return it after the transaction is done. From 69890aeba18e4d3d102f8d53d097057d0f29a850 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 14:34:45 +0200 Subject: [PATCH 31/59] chore: re add serde, restring HaltReasonTrait --- crates/primitives/src/chain_spec.rs | 17 +++++++++++------ crates/primitives/src/result.rs | 3 +++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 0d9164c90e..03eb6cf3a0 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -12,12 +12,17 @@ impl HardforkTrait for HardforkT where { } -/// The type that enumerates chain-specific halt reasons. -pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From {} - -impl HaltReasonTrait for HaltReasonT where - HaltReasonT: Clone + Debug + PartialEq + Eq + From -{ +cfg_if! { + if #[cfg(feature = "serde")] { + pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} + + impl HaltReasonTrait for HaltReasonT where + HaltReasonT: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} + } else { + pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From {} + impl HaltReasonTrait for HaltReasonT where + HaltReasonT: Clone + Debug + PartialEq + Eq + From {} + } } pub trait TransactionValidation { diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 89f2eb462c..3401a24582 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -19,6 +19,7 @@ pub type EVMErrorForChain = EVMError< >; #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ResultAndState { /// Status of execution pub result: ExecutionResult, @@ -29,6 +30,7 @@ pub struct ResultAndState { /// Result of a transaction execution. #[derive(Debug, PartialEq, Eq, Hash)] #[derive_where(Clone; EvmWiringT::HaltReason)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ExecutionResult { /// Returned successfully Success { @@ -145,6 +147,7 @@ impl Output { /// Main EVM error. #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum EVMError { /// Transaction validation error. Transaction(TransactionValidationErrorT), From 9a6d2e6a116125e5e6540d94c7d29676aadfc0c6 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 14:43:44 +0200 Subject: [PATCH 32/59] chore: move custom opcode to examples --- crates/revm/Cargo.toml | 5 +++ .../custom_opcodes.rs | 32 +++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) rename crates/revm/src/custom_upcode.rs => examples/custom_opcodes.rs (92%) diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 173982973c..62c4e62aa2 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -143,6 +143,11 @@ required-features = ["std", "serde-json"] #path = "../../examples/uniswap_v2_usdc_swap.rs" #required-features = ["alloydb"] +[[example]] +name = "custom_opcodes" +path = "../../examples/custom_opcodes.rs" +required-features = ["enumn"] + [[bench]] name = "bench" path = "benches/bench.rs" diff --git a/crates/revm/src/custom_upcode.rs b/examples/custom_opcodes.rs similarity index 92% rename from crates/revm/src/custom_upcode.rs rename to examples/custom_opcodes.rs index 1c172fbc28..72f4930a83 100644 --- a/crates/revm/src/custom_upcode.rs +++ b/examples/custom_opcodes.rs @@ -4,7 +4,7 @@ use revm_interpreter::{ Host, Interpreter, }; -use crate::{ +use revm::{ handler::register::EvmHandler, primitives::{db::Database, EvmWiring, HaltReason, Spec, SpecId}, }; @@ -215,18 +215,18 @@ macro_rules! custom_opcode_spec_to_generic { }}; } -impl EvmHandler<'_, CustomOpcodeEvmWiring, EXT, DB> { - pub fn custom_opcode_with_spec(spec_id: CustomOpcodeSpecId) -> Self { - let mut handler = Self::mainnet_with_spec(spec_id); +// impl EvmHandler<'_, CustomOpcodeEvmWiring, EXT, DB> { +// pub fn custom_opcode_with_spec(spec_id: CustomOpcodeSpecId) -> Self { +// let mut handler = Self::mainnet_with_spec(spec_id); - custom_opcode_spec_to_generic!(spec_id, { - let table = make_custom_instruction_table::<_, SPEC>(); - handler.set_instruction_table(InstructionTables::Plain(table)); - }); +// custom_opcode_spec_to_generic!(spec_id, { +// let table = make_custom_instruction_table::<_, SPEC>(); +// handler.set_instruction_table(InstructionTables::Plain(table)); +// }); - handler - } -} +// handler +// } +// } fn make_custom_instruction_table< EvmWiringT: EvmWiring, @@ -241,11 +241,7 @@ fn make_custom_instruction_table< table } -fn custom_opcode_handler< - EvmWiringT: EvmWiring, - H: Host + ?Sized, - SPEC: CustomOpcodeSpec, ->( +fn custom_opcode_handler( interpreter: &mut Interpreter, _host: &mut H, ) { @@ -258,3 +254,7 @@ fn custom_opcode_handler< // logic } + +pub fn main() { + println!("Example is in code compilation"); +} From da81d97e41327321f90baff90de2b574b425c727 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 15:10:35 +0200 Subject: [PATCH 33/59] chore: remove op feature from test wiring --- crates/revm/src/handler.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 12e2a244c5..471e27237e 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -198,9 +198,6 @@ mod test { use super::*; - #[cfg(feature = "optimism")] - type TestEvmWiring = crate::optimism::EvmWiring; - #[cfg(not(feature = "optimism"))] type TestEvmWiring = primitives::EthereumWiring; #[test] From 1ad97fdc3623752c35b57244594a22595ebe5acd Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 15:13:01 +0200 Subject: [PATCH 34/59] nit use Self::EvmWiringT --- crates/interpreter/src/host/dummy.rs | 4 ++-- crates/revm/src/context.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index f2e816cb64..8438fae6c0 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -52,12 +52,12 @@ where type EvmWiringT = EvmWiringT; #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &Env { &self.env } #[inline] - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut Env { &mut self.env } diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index eeac20e9ae..a9e964e0d2 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -91,7 +91,7 @@ impl Host for Context &Env { + fn env(&self) -> &Env { &self.evm.env } From 6d479da35cf431da4276f374a39291cc3872b336 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Jul 2024 16:31:36 +0200 Subject: [PATCH 35/59] nit indents --- .../interpreter_action/eof_create_inputs.rs | 2 +- crates/interpreter/src/opcode.rs | 76 +++++++++---------- crates/revm/Cargo.toml | 2 +- .../revm/src/context/context_precompiles.rs | 6 +- crates/revm/src/context/evm_context.rs | 2 +- crates/revm/src/context/inner_evm_context.rs | 2 +- crates/revm/src/evm.rs | 2 +- .../revm/src/handler/mainnet/pre_execution.rs | 4 +- crates/revm/src/optimism/handler_register.rs | 2 +- examples/custom_opcodes.rs | 31 +++++--- 10 files changed, 70 insertions(+), 59 deletions(-) diff --git a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs index 5846d66fee..ade9c0a0a8 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs @@ -1,6 +1,6 @@ use revm_primitives::EvmWiring; -use crate::primitives::{Address, Bytes, Eof, Transaction as _, U256}; +use crate::primitives::{Address, Bytes, Eof, Transaction, U256}; /// EOF create can be called from two places: /// * EOFCREATE opcode diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index a07f4ae6e7..02172cf75f 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -427,32 +427,32 @@ macro_rules! opcodes { opcodes! { 0x00 => STOP => control::stop => stack_io(0, 0), terminating; - 0x01 => ADD => arithmetic::add => stack_io(2, 1); - 0x02 => MUL => arithmetic::mul => stack_io(2, 1); - 0x03 => SUB => arithmetic::sub => stack_io(2, 1); - 0x04 => DIV => arithmetic::div => stack_io(2, 1); - 0x05 => SDIV => arithmetic::sdiv => stack_io(2, 1); - 0x06 => MOD => arithmetic::rem => stack_io(2, 1); - 0x07 => SMOD => arithmetic::smod => stack_io(2, 1); - 0x08 => ADDMOD => arithmetic::addmod => stack_io(3, 1); - 0x09 => MULMOD => arithmetic::mulmod => stack_io(3, 1); + 0x01 => ADD => arithmetic::add => stack_io(2, 1); + 0x02 => MUL => arithmetic::mul => stack_io(2, 1); + 0x03 => SUB => arithmetic::sub => stack_io(2, 1); + 0x04 => DIV => arithmetic::div => stack_io(2, 1); + 0x05 => SDIV => arithmetic::sdiv => stack_io(2, 1); + 0x06 => MOD => arithmetic::rem => stack_io(2, 1); + 0x07 => SMOD => arithmetic::smod => stack_io(2, 1); + 0x08 => ADDMOD => arithmetic::addmod => stack_io(3, 1); + 0x09 => MULMOD => arithmetic::mulmod => stack_io(3, 1); 0x0A => EXP => arithmetic::exp:: => stack_io(2, 1); - 0x0B => SIGNEXTEND => arithmetic::signextend => stack_io(2, 1); + 0x0B => SIGNEXTEND => arithmetic::signextend => stack_io(2, 1); // 0x0C // 0x0D // 0x0E // 0x0F - 0x10 => LT => bitwise::lt => stack_io(2, 1); - 0x11 => GT => bitwise::gt => stack_io(2, 1); - 0x12 => SLT => bitwise::slt => stack_io(2, 1); - 0x13 => SGT => bitwise::sgt => stack_io(2, 1); - 0x14 => EQ => bitwise::eq => stack_io(2, 1); - 0x15 => ISZERO => bitwise::iszero => stack_io(1, 1); - 0x16 => AND => bitwise::bitand => stack_io(2, 1); - 0x17 => OR => bitwise::bitor => stack_io(2, 1); - 0x18 => XOR => bitwise::bitxor => stack_io(2, 1); - 0x19 => NOT => bitwise::not => stack_io(1, 1); - 0x1A => BYTE => bitwise::byte => stack_io(2, 1); + 0x10 => LT => bitwise::lt => stack_io(2, 1); + 0x11 => GT => bitwise::gt => stack_io(2, 1); + 0x12 => SLT => bitwise::slt => stack_io(2, 1); + 0x13 => SGT => bitwise::sgt => stack_io(2, 1); + 0x14 => EQ => bitwise::eq => stack_io(2, 1); + 0x15 => ISZERO => bitwise::iszero => stack_io(1, 1); + 0x16 => AND => bitwise::bitand => stack_io(2, 1); + 0x17 => OR => bitwise::bitor => stack_io(2, 1); + 0x18 => XOR => bitwise::bitxor => stack_io(2, 1); + 0x19 => NOT => bitwise::not => stack_io(1, 1); + 0x1A => BYTE => bitwise::byte => stack_io(2, 1); 0x1B => SHL => bitwise::shl:: => stack_io(2, 1); 0x1C => SHR => bitwise::shr:: => stack_io(2, 1); 0x1D => SAR => bitwise::sar:: => stack_io(2, 1); @@ -474,18 +474,18 @@ opcodes! { // 0x2D // 0x2E // 0x2F - 0x30 => ADDRESS => system::address => stack_io(0, 1); + 0x30 => ADDRESS => system::address => stack_io(0, 1); 0x31 => BALANCE => host::balance:: => stack_io(1, 1); - 0x32 => ORIGIN => host_env::origin => stack_io(0, 1); - 0x33 => CALLER => system::caller => stack_io(0, 1); - 0x34 => CALLVALUE => system::callvalue => stack_io(0, 1); - 0x35 => CALLDATALOAD => system::calldataload => stack_io(1, 1); - 0x36 => CALLDATASIZE => system::calldatasize => stack_io(0, 1); - 0x37 => CALLDATACOPY => system::calldatacopy => stack_io(3, 0); - 0x38 => CODESIZE => system::codesize => stack_io(0, 1), not_eof; - 0x39 => CODECOPY => system::codecopy => stack_io(3, 0), not_eof; - - 0x3A => GASPRICE => host_env::gasprice => stack_io(0, 1); + 0x32 => ORIGIN => host_env::origin => stack_io(0, 1); + 0x33 => CALLER => system::caller => stack_io(0, 1); + 0x34 => CALLVALUE => system::callvalue => stack_io(0, 1); + 0x35 => CALLDATALOAD => system::calldataload => stack_io(1, 1); + 0x36 => CALLDATASIZE => system::calldatasize => stack_io(0, 1); + 0x37 => CALLDATACOPY => system::calldatacopy => stack_io(3, 0); + 0x38 => CODESIZE => system::codesize => stack_io(0, 1), not_eof; + 0x39 => CODECOPY => system::codecopy => stack_io(3, 0), not_eof; + + 0x3A => GASPRICE => host_env::gasprice => stack_io(0, 1); 0x3B => EXTCODESIZE => host::extcodesize:: => stack_io(1, 1), not_eof; 0x3C => EXTCODECOPY => host::extcodecopy:: => stack_io(4, 0), not_eof; 0x3D => RETURNDATASIZE => system::returndatasize:: => stack_io(0, 1); @@ -507,10 +507,10 @@ opcodes! { // 0x4D // 0x4E // 0x4F - 0x50 => POP => stack::pop => stack_io(1, 0); - 0x51 => MLOAD => memory::mload => stack_io(1, 1); - 0x52 => MSTORE => memory::mstore => stack_io(2, 0); - 0x53 => MSTORE8 => memory::mstore8 => stack_io(2, 0); + 0x50 => POP => stack::pop => stack_io(1, 0); + 0x51 => MLOAD => memory::mload => stack_io(1, 1); + 0x52 => MSTORE => memory::mstore => stack_io(2, 0); + 0x53 => MSTORE8 => memory::mstore8 => stack_io(2, 0); 0x54 => SLOAD => host::sload:: => stack_io(1, 1); 0x55 => SSTORE => host::sstore:: => stack_io(2, 0); 0x56 => JUMP => control::jump => stack_io(1, 0), not_eof; @@ -674,7 +674,7 @@ opcodes! { 0xF0 => CREATE => contract::create:: => stack_io(3, 1), not_eof; 0xF1 => CALL => contract::call:: => stack_io(7, 1), not_eof; 0xF2 => CALLCODE => contract::call_code:: => stack_io(7, 1), not_eof; - 0xF3 => RETURN => control::ret => stack_io(2, 0), terminating; + 0xF3 => RETURN => control::ret => stack_io(2, 0), terminating; 0xF4 => DELEGATECALL => contract::delegate_call:: => stack_io(6, 1), not_eof; 0xF5 => CREATE2 => contract::create:: => stack_io(4, 1), not_eof; // 0xF6 @@ -685,7 +685,7 @@ opcodes! { 0xFB => EXTSTATICCALL => contract::extstaticcall => stack_io(3, 1); // 0xFC 0xFD => REVERT => control::revert:: => stack_io(2, 0), terminating; - 0xFE => INVALID => control::invalid => stack_io(0, 0), terminating; + 0xFE => INVALID => control::invalid => stack_io(0, 0), terminating; 0xFF => SELFDESTRUCT => host::selfdestruct:: => stack_io(1, 0), not_eof, terminating; } diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 62c4e62aa2..d27693c93c 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -146,7 +146,7 @@ required-features = ["std", "serde-json"] [[example]] name = "custom_opcodes" path = "../../examples/custom_opcodes.rs" -required-features = ["enumn"] +required-features = [] [[bench]] name = "bench" diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index ac96105ff3..e0aa98883e 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -25,9 +25,9 @@ pub enum ContextPrecompile { impl Debug for ContextPrecompile { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::Ordinary(arg0) => f.debug_tuple("Ordinary").field(arg0).finish(), - Self::ContextStateful(_arg0) => f.debug_tuple("ContextStateful").finish(), - Self::ContextStatefulMut(_arg0) => f.debug_tuple("ContextStatefulMut").finish(), + Self::Ordinary(p) => f.debug_tuple("Ordinary").field(p).finish(), + Self::ContextStateful(_) => f.debug_tuple("ContextStateful").finish(), + Self::ContextStatefulMut(_) => f.debug_tuple("ContextStatefulMut").finish(), } } } diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 7f5b8c7111..16c0b707a9 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -12,7 +12,7 @@ use crate::{ primitives::{ keccak256, Address, Bytecode, Bytes, CreateScheme, EVMError, EVMResultGeneric, Env, Eof, SpecId::{self, *}, - Transaction as _, B256, EOF_MAGIC_BYTES, + Transaction, B256, EOF_MAGIC_BYTES, }, ContextPrecompiles, EvmWiring, FrameOrResult, CALL_STACK_LIMIT, }; diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index f263518ac6..1e694279c4 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -11,7 +11,7 @@ use crate::{ AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, Env, Eof, EvmWiring, HashSet, Spec, SpecId::{self, *}, - Transaction as _, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, + Transaction, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, JournalCheckpoint, }; diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 1dc9dcaedd..12cac0d7e8 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -7,7 +7,7 @@ use crate::{ interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthereumWiring, ExecutionResult, - ResultAndState, SpecId, Transaction as _, TxKind, EOF_MAGIC_BYTES, + ResultAndState, SpecId, Transaction, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithEvmWiring, EvmWiring, Frame, FrameOrResult, FrameResult, }; diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index e67c4dd233..90d409ab0c 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -5,8 +5,8 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ - db::Database, Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, - Transaction as _, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, + db::Database, Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction, + BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, EvmWiring, }; diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 3a0b6218b7..6a526a4499 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use super::{ OptimismContext, OptimismHaltReason, OptimismInvalidTransaction, OptimismSpec, OptimismSpecId, - OptimismTransaction as _, OptimismWiring, + OptimismTransaction, OptimismWiring, }; pub fn optimism_handle_register( diff --git a/examples/custom_opcodes.rs b/examples/custom_opcodes.rs index 72f4930a83..62b3abe4ac 100644 --- a/examples/custom_opcodes.rs +++ b/examples/custom_opcodes.rs @@ -1,13 +1,12 @@ -use revm_interpreter::{ - gas, - opcode::{make_instruction_table, InstructionTable, InstructionTables}, - Host, Interpreter, -}; - use revm::{ - handler::register::EvmHandler, - primitives::{db::Database, EvmWiring, HaltReason, Spec, SpecId}, + interpreter::{ + gas, + opcode::{make_instruction_table, InstructionTable}, + Host, Interpreter, + }, + primitives::{BlockEnv, EvmWiring, HaltReason, Spec, SpecId, TxEnv}, }; +use revm_interpreter::DummyHost; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct CustomOpcodeEvmWiring; @@ -15,11 +14,13 @@ pub struct CustomOpcodeEvmWiring; impl EvmWiring for CustomOpcodeEvmWiring { type Hardfork = CustomOpcodeSpecId; type HaltReason = HaltReason; + type Block = BlockEnv; + type Transaction = TxEnv; } /// Specification IDs for the optimism blockchain. #[repr(u8)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[allow(non_camel_case_types, clippy::upper_case_acronyms)] pub enum CustomOpcodeSpecId { @@ -228,7 +229,7 @@ macro_rules! custom_opcode_spec_to_generic { // } // } -fn make_custom_instruction_table< +pub fn make_custom_instruction_table< EvmWiringT: EvmWiring, H: Host + ?Sized, SPEC: CustomOpcodeSpec, @@ -257,4 +258,14 @@ fn custom_opcode_handler( pub fn main() { println!("Example is in code compilation"); + let spec_id = CustomOpcodeSpecId::INTRODUCES_OPCODE; + + let _instructions = custom_opcode_spec_to_generic!( + spec_id, + make_custom_instruction_table::< + CustomOpcodeEvmWiring, + DummyHost, + SPEC, + >() + ); } From 1bce03799856d4c0f11bc85751e6a1eea016499a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 1 Aug 2024 13:50:54 +0200 Subject: [PATCH 36/59] feat(Wiring): Add Database and EXT to EvmWiring --- crates/interpreter/src/host.rs | 6 +- .../interpreter/src/instructions/bitwise.rs | 10 +- .../interpreter/src/instructions/control.rs | 18 +- crates/interpreter/src/instructions/data.rs | 6 +- crates/interpreter/src/instructions/stack.rs | 9 +- crates/interpreter/src/instructions/system.rs | 6 +- crates/interpreter/src/interpreter.rs | 16 +- crates/primitives/src/chain_spec.rs | 21 ++- crates/primitives/src/db.rs | 3 + crates/{revm => primitives}/src/db/emptydb.rs | 6 +- crates/primitives/src/env.rs | 19 +- crates/primitives/src/result.rs | 12 +- crates/revm/src/builder.rs | 42 ++--- crates/revm/src/chain_spec.rs | 17 +- crates/revm/src/context.rs | 47 +++-- .../revm/src/context/context_precompiles.rs | 65 +++---- crates/revm/src/context/evm_context.rs | 72 ++++---- crates/revm/src/context/inner_evm_context.rs | 70 +++++--- crates/revm/src/db.rs | 3 +- crates/revm/src/evm.rs | 63 ++++--- crates/revm/src/handler.rs | 90 ++++------ .../src/handler/handle_types/execution.rs | 169 ++++++++---------- .../handler/handle_types/post_execution.rs | 80 ++++----- .../src/handler/handle_types/pre_execution.rs | 52 +++--- .../src/handler/handle_types/validation.rs | 53 +++--- crates/revm/src/handler/mainnet/execution.rs | 79 ++++---- .../src/handler/mainnet/post_execution.rs | 32 ++-- .../revm/src/handler/mainnet/pre_execution.rs | 17 +- crates/revm/src/handler/mainnet/validation.rs | 16 +- crates/revm/src/handler/register.rs | 23 ++- crates/revm/src/inspector.rs | 27 ++- crates/revm/src/inspector/customprinter.rs | 16 +- crates/revm/src/inspector/eip3155.rs | 14 +- crates/revm/src/inspector/gas.rs | 32 ++-- crates/revm/src/inspector/handler_register.rs | 49 +++-- crates/revm/src/inspector/noop.rs | 4 +- crates/revm/src/optimism/handler_register.rs | 14 +- 37 files changed, 607 insertions(+), 671 deletions(-) rename crates/{revm => primitives}/src/db/emptydb.rs (97%) diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index f438638bce..63f156224f 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -88,7 +88,7 @@ pub struct SelfDestructResult { #[cfg(test)] mod tests { - use revm_primitives::EthereumWiring; + use revm_primitives::{db::EmptyDB, EthereumWiring}; use super::*; @@ -96,7 +96,7 @@ mod tests { #[test] fn object_safety() { - assert_host::>(); - assert_host::>(); + assert_host::>>(); + assert_host::>>(); } } diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index e10c2987ca..9da8d77a44 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -125,7 +125,7 @@ pub fn sar(interpreter: &mut Interpreter, _host: & mod tests { use crate::instructions::bitwise::{byte, sar, shl, shr}; use crate::{Contract, DummyHost, Interpreter}; - use revm_primitives::{uint, Env, EthereumWiring, LatestSpec, U256}; + use revm_primitives::{uint, DefaultEthereumWiring, Env, LatestSpec, U256}; #[test] fn test_shift_left() { @@ -202,7 +202,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shl::, LatestSpec>(&mut interpreter, &mut host); + shl::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -283,7 +283,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - shr::, LatestSpec>(&mut interpreter, &mut host); + shr::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -389,7 +389,7 @@ mod tests { host.clear(); push!(interpreter, test.value); push!(interpreter, test.shift); - sar::, LatestSpec>(&mut interpreter, &mut host); + sar::, LatestSpec>(&mut interpreter, &mut host); pop!(interpreter, res); assert_eq!(res, test.expected); } @@ -403,7 +403,7 @@ mod tests { expected: U256, } - let mut host = DummyHost::new(Env::::default()); + let mut host = DummyHost::new(Env::::default()); let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index a3ec57c91c..ed593dedf0 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -206,7 +206,7 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { mod test { use std::sync::Arc; - use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, EthereumWiring, PragueSpec}; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, DefaultEthereumWiring, PragueSpec}; use super::*; use crate::{ @@ -216,7 +216,7 @@ mod test { #[test] fn rjump() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMP, 0x00, 0x02, STOP, STOP, @@ -230,7 +230,7 @@ mod test { #[test] fn rjumpi() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPI, 0x00, 0x03, RJUMPI, 0x00, 0x01, STOP, STOP, @@ -250,7 +250,7 @@ mod test { #[test] fn rjumpv() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ RJUMPV, @@ -332,7 +332,7 @@ mod test { #[test] fn callf_retf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]); let bytes2 = Bytes::from([RETF]); @@ -363,7 +363,7 @@ mod test { #[test] fn callf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -387,7 +387,7 @@ mod test { #[test] fn callf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -404,7 +404,7 @@ mod test { #[test] fn jumpf_stop() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); @@ -425,7 +425,7 @@ mod test { #[test] fn jumpf_stack_overflow() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); let bytes2 = Bytes::from([STOP]); diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index 180c11054b..f09d4ecd68 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -83,7 +83,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { - use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, EthereumWiring, PragueSpec}; + use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, DefaultEthereumWiring, PragueSpec}; use std::sync::Arc; use super::*; @@ -107,7 +107,7 @@ mod test { #[test] fn dataload_dataloadn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([ DATALOAD, DATALOADN, 0x00, 0x00, DATALOAD, DATALOADN, 0x00, 35, DATALOAD, DATALOADN, @@ -163,7 +163,7 @@ mod test { #[test] fn data_copy() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let eof = dummy_eof(Bytes::from([DATACOPY, DATACOPY, DATACOPY, DATACOPY])); diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index 99894658ed..f249823b4d 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -86,16 +86,17 @@ pub fn exchange(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { + use super::*; use crate::{ opcode::{make_instruction_table, DUPN, EXCHANGE, SWAPN}, - primitives::{Bytecode, Bytes, EthereumWiring, PragueSpec}, + primitives::{Bytecode, Bytes, DefaultEthereumWiring, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn dupn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ DUPN, 0x00, DUPN, 0x01, DUPN, 0x02, @@ -115,7 +116,7 @@ mod test { #[test] fn swapn() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([SWAPN, 0x00, SWAPN, 0x01]))); @@ -135,7 +136,7 @@ mod test { #[test] fn exchange() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw(Bytes::from([ EXCHANGE, 0x00, EXCHANGE, 0x11, diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index f30d0cc397..659951f733 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -189,13 +189,13 @@ mod test { use super::*; use crate::{ opcode::{make_instruction_table, RETURNDATACOPY, RETURNDATALOAD}, - primitives::{bytes, Bytecode, EthereumWiring, PragueSpec}, + primitives::{bytes, Bytecode, DefaultEthereumWiring, PragueSpec}, DummyHost, Gas, InstructionResult, }; #[test] fn returndataload() { - let table = make_instruction_table::, PragueSpec>(); + let table = make_instruction_table::, PragueSpec>(); let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( @@ -254,7 +254,7 @@ mod test { #[test] fn returndatacopy() { let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::::default(); + let mut host = DummyHost::::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( [ diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 0aacbe170c..1533582bbd 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -469,22 +469,22 @@ pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) mod tests { use super::*; use crate::{opcode::InstructionTable, DummyHost}; - use revm_primitives::{CancunSpec, EthereumWiring}; + use revm_primitives::{CancunSpec, DefaultEthereumWiring, EthereumWiring}; #[test] fn object_safety() { let mut interp = Interpreter::new(Contract::default(), u64::MAX, false); - let mut host = crate::DummyHost::::default(); - let table: &InstructionTable> = - &crate::opcode::make_instruction_table::, CancunSpec>(); + let mut host = crate::DummyHost::::default(); + let table: &InstructionTable> = + &crate::opcode::make_instruction_table::, CancunSpec>(); let _ = interp.run(EMPTY_SHARED_MEMORY, table, &mut host); - let host: &mut dyn Host = - &mut host as &mut dyn Host; - let table: &InstructionTable> = + let host: &mut dyn Host = + &mut host as &mut dyn Host; + let table: &InstructionTable> = &crate::opcode::make_instruction_table::< - dyn Host, + dyn Host, CancunSpec, >(); let _ = interp.run(EMPTY_SHARED_MEMORY, table, host); diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 03eb6cf3a0..9ecfc1632b 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -1,6 +1,6 @@ use cfg_if::cfg_if; -use crate::{Block, SpecId, Transaction}; +use crate::{db::Database, Block, SpecId, Transaction}; use core::{fmt::Debug, hash::Hash}; @@ -37,7 +37,13 @@ pub trait TransactionValidation { } } -pub trait EvmWiring: Sized + 'static { + +pub trait EvmWiring: Sized { + /// External type + type ExternalContext: Sized; + /// Database type. + type Database: Database; + /// The type that contains all block information. type Block: Block; @@ -49,14 +55,21 @@ pub trait EvmWiring: Sized + 'static { /// Halt reason type. type HaltReason: HaltReasonTrait; + } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct EthereumWiring; +pub struct EthereumWiring { + phantom: core::marker::PhantomData<(DB, EXT)>, +} -impl EvmWiring for EthereumWiring { +impl EvmWiring for EthereumWiring { + type Database = DB; + type ExternalContext = EXT; type Block = crate::BlockEnv; type Hardfork = SpecId; type HaltReason = crate::HaltReason; type Transaction = crate::TxEnv; } + +pub type DefaultEthereumWiring = EthereumWiring; diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index d0dfc464af..0b01009831 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -2,9 +2,12 @@ use crate::{Account, AccountInfo, Address, Bytecode, HashMap, B256, U256}; use auto_impl::auto_impl; pub mod components; +pub mod emptydb; + pub use components::{ BlockHash, BlockHashRef, DatabaseComponentError, DatabaseComponents, State, StateRef, }; +pub use emptydb::{EmptyDB, EmptyDBTyped}; /// EVM database interface. #[auto_impl(&mut, Box)] diff --git a/crates/revm/src/db/emptydb.rs b/crates/primitives/src/db/emptydb.rs similarity index 97% rename from crates/revm/src/db/emptydb.rs rename to crates/primitives/src/db/emptydb.rs index 3d14ab23ae..8f9783e82a 100644 --- a/crates/revm/src/db/emptydb.rs +++ b/crates/primitives/src/db/emptydb.rs @@ -1,8 +1,8 @@ -use core::{convert::Infallible, fmt, marker::PhantomData}; -use revm_interpreter::primitives::{ +use crate::{ db::{Database, DatabaseRef}, keccak256, AccountInfo, Address, Bytecode, B256, U256, }; +use core::{convert::Infallible, fmt, marker::PhantomData}; use std::string::ToString; /// An empty database that always returns default values when queried. @@ -104,7 +104,7 @@ impl DatabaseRef for EmptyDBTyped { #[cfg(test)] mod tests { use super::*; - use crate::primitives::b256; + use crate::b256; #[test] fn conform_block_hash_calculation() { diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 11c9292da2..3761aa6b58 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -36,6 +36,19 @@ impl Env { Box::new(Self { cfg, block, tx }) } + /// Transforms Evn to different Wiring with has same block and transaction. + pub fn into_evm_wiring< + OWiring: EvmWiring, + >( + self, + ) -> Env { + Env { + cfg: self.cfg, + block: self.block, + tx: self.tx, + } + } + /// Calculates the effective gas price of the transaction. #[inline] pub fn effective_gas_price(&self) -> U256 { @@ -767,13 +780,13 @@ pub enum AnalysisKind { #[cfg(test)] mod tests { - use crate::EthereumWiring; + use crate::{db::EmptyDB, EthereumWiring}; use super::*; #[test] fn test_validate_tx_chain_id() { - let mut env = Env::::default(); + let mut env = Env::>::default(); env.tx.chain_id = Some(1); env.cfg.chain_id = 2; assert_eq!( @@ -784,7 +797,7 @@ mod tests { #[test] fn test_validate_tx_access_list() { - let mut env = Env::::default(); + let mut env = Env::>::default(); env.tx.access_list = vec![AccessListItem { address: Address::ZERO, storage_keys: vec![], diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 3401a24582..361f34359f 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,20 +1,18 @@ use derive_where::derive_where; -use crate::{Address, Bytes, EvmState, EvmWiring, Log, TransactionValidation, U256}; +use crate::{db::Database, Address, Bytes, EvmState, EvmWiring, Log, TransactionValidation, U256}; use core::fmt::{self, Debug}; use std::{boxed::Box, string::String, vec::Vec}; /// Result of EVM execution. -pub type EVMResult = - EVMResultGeneric, EvmWiringT, DBError>; +pub type EVMResult = EVMResultGeneric, EvmWiringT>; /// Generic result of EVM execution. Used to represent error and generic output. -pub type EVMResultGeneric = - core::result::Result>; +pub type EVMResultGeneric = core::result::Result>; /// EVM error type for a specific chain. -pub type EVMErrorForChain = EVMError< - DBError, +pub type EVMErrorForChain = EVMError< + <::Database as Database>::Error, <::Transaction as TransactionValidation>::ValidationError, >; diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index bf381abebd..44ce195629 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -10,10 +10,10 @@ use std::boxed::Box; /// Evm Builder allows building or modifying EVM. /// Note that some of the methods that changes underlying structures /// will reset the registered handler to default mainnet. -pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> { - context: Context, +pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring> { + context: Context, /// Handler that will be used by EVM. It contains handle registers - handler: Handler<'a, EvmWiringT, Context, EXT, DB>, + handler: Handler<'a, EvmWiringT, Context>, /// Phantom data to mark the stage of the builder. phantom: PhantomData, } @@ -26,26 +26,24 @@ pub struct SetGenericStage; /// Requires the database and external context to be set. pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring, (), EmptyDB> { +impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring> { fn default() -> Self { Self { context: Context::default(), - handler: EthereumWiring::handler::<'a, (), EmptyDB>( - ::Hardfork::default(), + handler: EthereumWiring::handler::<'a>( + as primitives::EvmWiring>::Hardfork::default(), ), phantom: PhantomData, } } } -impl<'a, EvmWiringT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, DB> +impl<'a, EvmWiringT> EvmBuilder<'a, SetGenericStage, EvmWiringT> where EvmWiringT: EvmWiring, { /// Sets the [`EvmWiring`] that will be used by [`Evm`]. - pub fn with_chain_spec( - self, - ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT, EXT, DB> + pub fn with_chain_spec(self) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> where NewEvmWiringT: EvmWiring< Block: Default, @@ -56,7 +54,7 @@ where EvmBuilder { context: Context::new(EvmContext::new(evm.inner.db), external), - handler: NewEvmWiringT::handler::<'a, EXT, DB>(NewEvmWiringT::Hardfork::default()), + handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), phantom: PhantomData, } } @@ -146,25 +144,23 @@ where pub fn with_cfg_env_with_handler_cfg( mut self, cfg_env_and_spec_id: CfgEnvWithEvmWiring, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; EvmBuilder { context: self.context, - handler: EvmWiringT::handler::<'a, EXT, DB>(cfg_env_and_spec_id.spec_id), + handler: EvmWiringT::handler::<'a>(cfg_env_and_spec_id.spec_id), phantom: PhantomData, } } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> - EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> -{ +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, HandlerStage, EvmWiringT> { /// Creates new builder from Evm, Evm is consumed and all field are moved to Builder. /// It will preserve set handler and context. /// /// Builder is in HandlerStage and both database and external are set. - pub fn new(evm: Evm<'a, EvmWiringT, EXT, DB>) -> Self { + pub fn new(evm: Evm<'a, EvmWiringT>) -> Self { Self { context: evm.context, handler: evm.handler, @@ -173,7 +169,7 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, HandlerStage, EvmWiringT> where EvmWiringT: EvmWiring>>, @@ -256,7 +252,7 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> /// ``` pub fn with_handler( self, - handler: Handler<'a, EvmWiringT, Context, EXT, DB>, + handler: Handler<'a, EvmWiringT, Context, EXT, DB>, ) -> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> { EvmBuilder { context: self.context, @@ -397,8 +393,7 @@ where } } -impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> - EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWiringT> where EvmWiringT: EvmWiring>>, @@ -422,7 +417,8 @@ where /// Resets [`Handler`] to default mainnet. pub fn reset_handler(mut self) -> Self { - self.handler = EvmWiringT::handler::<'a, EXT, DB>(self.handler.spec_id()); + self.handler = + EvmWiringT::::handler::<'a>(self.handler.spec_id()); self } } @@ -442,7 +438,7 @@ mod test { use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; - type TestEvmWiring = crate::primitives::EthereumWiring; + type TestEvmWiring = crate::primitives::DefaultEthereumWiring; /// Custom evm context #[derive(Default, Clone, Debug)] diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index 418a139ef1..5d0f62bac6 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -1,25 +1,18 @@ use crate::{ handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, interpreter::opcode::InstructionTables, - primitives::{db::Database, spec_to_generic, EthereumWiring}, + primitives::{db::Database, spec_to_generic, EthereumWiring, EvmWiring as PrimitiveEvmWiring}, EvmHandler, }; use std::vec::Vec; -pub trait EvmWiring: crate::primitives::EvmWiring { - /// The type that contains all context information for the chain's EVM execution. - type Context: Default; - +pub trait EvmWiring: PrimitiveEvmWiring { /// Creates a new handler with the given hardfork. - fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> - where - DB: Database; + fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self>; } -impl EvmWiring for EthereumWiring { - type Context = (); - - fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> +impl EvmWiring for EthereumWiring { + fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self> where DB: Database, { diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index a9e964e0d2..574615aa61 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -22,26 +22,16 @@ use crate::{ use std::boxed::Box; /// Main Context structure that contains both EvmContext and External context. -#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::Context, EvmWiringT::Transaction, DB, DB::Error, EXT)] -pub struct Context { +#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::Transaction, EvmWiringT::Database, ::Error, EvmWiringT::ExternalContext)] +pub struct Context { /// Evm Context (internal context). - pub evm: EvmContext, + pub evm: EvmContext, /// External contexts. - pub external: EXT, + pub external: EvmWiringT::ExternalContext, } -impl Default for Context { +impl Default for Context> { fn default() -> Self { - Self::new_empty() - } -} - -impl Context -where - EvmWiringT: EvmWiring, -{ - /// Creates empty context. This is useful for testing. - pub fn new_empty() -> Context { Context { evm: EvmContext::new(EmptyDB::new()), external: (), @@ -49,13 +39,13 @@ where } } -impl Context +impl Context where - EvmWiringT: EvmWiring, - DB: Database, + EvmWiringT: + EvmWiring, { /// Creates new context with database. - pub fn new_with_db(db: DB) -> Context { + pub fn new_with_db(db: EvmWiringT::Database) -> Context { Context { evm: EvmContext::new_with_env(db, Box::default()), external: (), @@ -63,30 +53,33 @@ where } } -impl Context { +impl Context { /// Creates new context with external and database. - pub fn new(evm: EvmContext, external: EXT) -> Context { + pub fn new( + evm: EvmContext, + external: EvmWiringT::ExternalContext, + ) -> Context { Context { evm, external } } } /// Context with handler configuration. -#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::Context, EvmWiringT::Transaction, DB, DB::Error, EXT)] -pub struct ContextWithEvmWiring { +#[derive_where(Clone; EvmWiringT::Block , EvmWiringT::Transaction,EvmWiringT::Database, ::Error, EvmWiringT::ExternalContext)] +pub struct ContextWithEvmWiring { /// Context of execution. - pub context: Context, + pub context: Context, /// Handler configuration. pub spec_id: EvmWiringT::Hardfork, } -impl ContextWithEvmWiring { +impl ContextWithEvmWiring { /// Creates new context with handler configuration. - pub fn new(context: Context, spec_id: EvmWiringT::Hardfork) -> Self { + pub fn new(context: Context, spec_id: EvmWiringT::Hardfork) -> Self { Self { spec_id, context } } } -impl Host for Context { +impl Host for Context { type EvmWiringT = EvmWiringT; /// Returns reference to Environment. diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index e0aa98883e..c3a1978d69 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -1,7 +1,7 @@ use super::InnerEvmContext; use crate::{ precompile::{Precompile, PrecompileResult}, - primitives::{db::Database, Address, Bytes, EvmWiring, HashMap, HashSet}, + primitives::{Address, Bytes, EvmWiring, HashMap, HashSet}, }; use core::fmt::Debug; use derive_where::derive_where; @@ -11,18 +11,18 @@ use std::{boxed::Box, sync::Arc}; /// A single precompile handler. #[derive_where(Clone)] -pub enum ContextPrecompile { +pub enum ContextPrecompile { /// Ordinary precompiles Ordinary(Precompile), /// Stateful precompile that is Arc over [`ContextStatefulPrecompile`] trait. /// It takes a reference to input, gas limit and Context. - ContextStateful(ContextStatefulPrecompileArc), + ContextStateful(ContextStatefulPrecompileArc), /// Mutable stateful precompile that is Box over [`ContextStatefulPrecompileMut`] trait. /// It takes a reference to input, gas limit and context. - ContextStatefulMut(ContextStatefulPrecompileBox), + ContextStatefulMut(ContextStatefulPrecompileBox), } -impl Debug for ContextPrecompile { +impl Debug for ContextPrecompile { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::Ordinary(p) => f.debug_tuple("Ordinary").field(p).finish(), @@ -33,20 +33,20 @@ impl Debug for ContextPrecompile { +enum PrecompilesCow { /// Default precompiles, returned by `Precompiles::new`. Used to fast-path the default case. StaticRef(&'static Precompiles), - Owned(HashMap>), + Owned(HashMap>), } /// Precompiles context. #[derive_where(Clone, Debug, Default)] -pub struct ContextPrecompiles { - inner: PrecompilesCow, +pub struct ContextPrecompiles { + inner: PrecompilesCow, } -impl ContextPrecompiles { +impl ContextPrecompiles { /// Creates a new precompiles context at the given spec ID. /// /// This is a cheap operation that does not allocate by reusing the global precompiles. @@ -68,9 +68,7 @@ impl ContextPrecompiles { /// Creates a new precompiles context from the given precompiles. #[inline] - pub fn from_precompiles( - precompiles: HashMap>, - ) -> Self { + pub fn from_precompiles(precompiles: HashMap>) -> Self { Self { inner: PrecompilesCow::Owned(precompiles), } @@ -111,7 +109,7 @@ impl ContextPrecompiles { address: &Address, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> Option { Some(match self.inner { PrecompilesCow::StaticRef(p) => { @@ -129,7 +127,7 @@ impl ContextPrecompiles { /// /// Clones the precompiles map if it is shared. #[inline] - pub fn to_mut(&mut self) -> &mut HashMap> { + pub fn to_mut(&mut self) -> &mut HashMap> { if let PrecompilesCow::StaticRef(_) = self.inner { self.mutate_into_owned(); } @@ -157,10 +155,10 @@ impl ContextPrecompiles { } } -impl Extend<(Address, ContextPrecompile)> - for ContextPrecompiles +impl Extend<(Address, ContextPrecompile)> + for ContextPrecompiles { - fn extend)>>( + fn extend)>>( &mut self, iter: T, ) { @@ -168,9 +166,7 @@ impl Extend<(Address, ContextPrecompile Extend - for ContextPrecompiles -{ +impl Extend for ContextPrecompiles { fn extend>(&mut self, iter: T) { self.to_mut().extend(iter.into_iter().map(|precompile| { let (address, precompile) = precompile.into(); @@ -179,7 +175,7 @@ impl Extend } } -impl Default for PrecompilesCow { +impl Default for PrecompilesCow { fn default() -> Self { Self::Owned(Default::default()) } @@ -187,39 +183,36 @@ impl Default for PrecompilesCow: Sync + Send { +pub trait ContextStatefulPrecompile: Sync + Send { fn call( &self, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> PrecompileResult; } /// Context aware mutable stateful precompile trait. It is used to create /// a boxed precompile in [`ContextPrecompile`]. -pub trait ContextStatefulPrecompileMut: - DynClone + Send + Sync -{ +pub trait ContextStatefulPrecompileMut: DynClone + Send + Sync { fn call_mut( &mut self, bytes: &Bytes, gas_limit: u64, - evmctx: &mut InnerEvmContext, + evmctx: &mut InnerEvmContext, ) -> PrecompileResult; } -dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); +dyn_clone::clone_trait_object!( ContextStatefulPrecompileMut); /// Arc over context stateful precompile. -pub type ContextStatefulPrecompileArc = - Arc>; +pub type ContextStatefulPrecompileArc = Arc>; /// Box over context mutable stateful precompile -pub type ContextStatefulPrecompileBox = - Box>; +pub type ContextStatefulPrecompileBox = + Box>; -impl From for ContextPrecompile { +impl From for ContextPrecompile { fn from(p: Precompile) -> Self { ContextPrecompile::Ordinary(p) } @@ -228,14 +221,14 @@ impl From for ContextPrecompile #[cfg(test)] mod tests { use super::*; - use crate::{db::EmptyDB, primitives::EthereumWiring}; + use crate::primitives::DefaultEthereumWiring; #[test] fn test_precompiles_context() { let custom_address = Address::with_last_byte(0xff); let mut precompiles = - ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); + ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); assert_eq!(precompiles.addresses().count(), 4); assert!(matches!(precompiles.inner, PrecompilesCow::StaticRef(_))); assert!(!precompiles.contains(&custom_address)); diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 16c0b707a9..779ff389f8 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -20,55 +20,49 @@ use core::ops::{Deref, DerefMut}; use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. -#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Context, EvmWiringT::Transaction, DB, DB::Error)] -pub struct EvmContext { - /// The context that's unique to the chain type. - pub chain: EvmWiringT::Context, +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Transaction, EvmWiringT::Database, ::Error)] +pub struct EvmContext { /// Inner EVM context. - pub inner: InnerEvmContext, + pub inner: InnerEvmContext, /// Precompiles that are available for evm. - pub precompiles: ContextPrecompiles, + pub precompiles: ContextPrecompiles, } -impl Deref for EvmContext { - type Target = InnerEvmContext; +impl Deref for EvmContext { + type Target = InnerEvmContext; fn deref(&self) -> &Self::Target { &self.inner } } -impl DerefMut for EvmContext { +impl DerefMut for EvmContext { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -impl EvmContext +impl EvmContext where EvmWiringT: EvmWiring, - DB: Database, { /// Create new context with database. - pub fn new(db: DB) -> Self { + pub fn new(db: EvmWiringT::Database) -> Self { Self { - chain: EvmWiringT::Context::default(), inner: InnerEvmContext::new(db), precompiles: ContextPrecompiles::default(), } } } -impl EvmContext +impl EvmContext where EvmWiringT: EvmWiring, - DB: Database, { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: DB, env: Box>) -> Self { + pub fn new_with_env(db: EvmWiringT::Database, env: Box>) -> Self { Self { - chain: EvmWiringT::Context::default(), inner: InnerEvmContext::new_with_env(db, env), precompiles: ContextPrecompiles::default(), } @@ -78,9 +72,13 @@ where /// /// Note that this will ignore the previous `error` if set. #[inline] - pub fn with_db(self, db: ODB) -> EvmContext { + pub fn with_db< + OEvmWiring: EvmWiring, + >( + self, + db: OEvmWiring::Database, + ) -> EvmContext { EvmContext { - chain: self.chain, inner: self.inner.with_db(db), precompiles: ContextPrecompiles::default(), } @@ -88,7 +86,7 @@ where /// Sets precompiles #[inline] - pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { + pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { // set warm loaded addresses. self.journaled_state .warm_preloaded_addresses @@ -103,7 +101,7 @@ where address: &Address, input_data: &Bytes, gas: Gas, - ) -> EVMResultGeneric, EvmWiringT, DB::Error> { + ) -> EVMResultGeneric, EvmWiringT> { let Some(outcome) = self.precompiles .call(address, input_data, gas.limit(), &mut self.inner) @@ -143,7 +141,7 @@ where pub fn make_call_frame( &mut self, inputs: &CallInputs, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -250,7 +248,7 @@ where &mut self, spec_id: SpecId, inputs: &CreateInputs, - ) -> Result { + ) -> Result::Error> { let return_error = |e| { Ok(FrameOrResult::new_create_result( InterpreterResult { @@ -344,7 +342,7 @@ where &mut self, spec_id: SpecId, inputs: &EOFCreateInputs, - ) -> Result { + ) -> Result::Error> { let return_error = |e| { Ok(FrameOrResult::new_eofcreate_result( InterpreterResult { @@ -479,11 +477,13 @@ pub(crate) mod test_utils { /// Creates an evm context with a cache db backend. /// Additionally loads the mock caller account into the db, /// and sets the balance to the provided U256 value. - pub fn create_cache_db_evm_context_with_balance( + pub fn create_cache_db_evm_context_with_balance< + EvmWiringT: EvmWiring>, + >( env: Box>, mut db: CacheDB, balance: U256, - ) -> EvmContext> { + ) -> EvmContext { db.insert_account_info( test_utils::MOCK_CALLER, crate::primitives::AccountInfo { @@ -497,12 +497,11 @@ pub(crate) mod test_utils { } /// Creates a cached db evm context. - pub fn create_cache_db_evm_context( + pub fn create_cache_db_evm_context>>( env: Box>, db: CacheDB, - ) -> EvmContext> { + ) -> EvmContext { EvmContext { - chain: EvmWiringT::Context::default(), inner: InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), @@ -515,12 +514,11 @@ pub(crate) mod test_utils { } /// Returns a new `EvmContext` with an empty journaled state. - pub fn create_empty_evm_context( + pub fn create_empty_evm_context>( env: Box>, db: EmptyDB, - ) -> EvmContext { + ) -> EvmContext { EvmContext { - chain: EvmWiringT::Context::default(), inner: InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), @@ -539,7 +537,7 @@ mod tests { use crate::primitives::U256; use crate::{ db::{CacheDB, EmptyDB}, - primitives::{address, Bytecode, EthereumWiring}, + primitives::{address, Bytecode, DefaultEthereumWiring, EthereumWiring}, Frame, JournalEntry, }; use std::boxed::Box; @@ -549,7 +547,7 @@ mod tests { // call stack is too deep. #[test] fn test_make_call_frame_stack_too_deep() { - let env = Env::::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut context = test_utils::create_empty_evm_context(Box::new(env), db); context.journaled_state.depth = CALL_STACK_LIMIT as usize + 1; @@ -570,7 +568,7 @@ mod tests { // checkpointed on the journaled state correctly. #[test] fn test_make_call_frame_transfer_revert() { - let env = Env::::default(); + let env = Env::::default(); let db = EmptyDB::default(); let mut evm_context = test_utils::create_empty_evm_context(Box::new(env), db); let contract = address!("dead10000000000000000000000000000001dead"); @@ -591,7 +589,7 @@ mod tests { #[test] fn test_make_call_frame_missing_code_context() { - let env = Env::::default(); + let env = Env::>::default(); let cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let mut context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); @@ -606,7 +604,7 @@ mod tests { #[test] fn test_make_call_frame_succeeds() { - let env = Env::::default(); + let env = Env::>::default(); let mut cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let by = Bytecode::new_raw(Bytes::from(vec![0x60, 0x00, 0x60, 0x00])); diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 1e694279c4..a702a4d878 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -18,27 +18,26 @@ use crate::{ use std::{boxed::Box, sync::Arc, vec::Vec}; /// EVM contexts contains data that EVM needs for execution. -#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Transaction, DB, DB::Error)] -pub struct InnerEvmContext { +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Transaction, EvmWiringT::Database, ::Error)] +pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. pub env: Box>, /// EVM State with journaling support. pub journaled_state: JournaledState, /// Database to load data from. - pub db: DB, + pub db: EvmWiringT::Database, /// Error that happened during execution. - pub error: Result<(), DB::Error>, + pub error: Result<(), ::Error>, /// EIP-7702 Authorization list of accounts that needs to be cleared. pub valid_authorizations: Vec
, } -impl InnerEvmContext +impl InnerEvmContext where EvmWiringT: EvmWiring, - DB: Database, { - pub fn new(db: DB) -> Self { + pub fn new(db: EvmWiringT::Database) -> Self { Self { env: Box::default(), journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), @@ -49,10 +48,10 @@ where } } -impl InnerEvmContext { +impl InnerEvmContext { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: DB, env: Box>) -> Self { + pub fn new_with_env(db: EvmWiringT::Database, env: Box>) -> Self { Self { env, journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), @@ -66,9 +65,14 @@ impl InnerEvmContext { /// /// Note that this will ignore the previous `error` if set. #[inline] - pub fn with_db(self, db: ODB) -> InnerEvmContext { + pub fn with_db< + OWiring: EvmWiring, + >( + self, + db: OWiring::Database, + ) -> InnerEvmContext { InnerEvmContext { - env: self.env, + env: Box::new(self.env.into_evm_wiring::()), journaled_state: self.journaled_state, db, error: Ok(()), @@ -86,7 +90,7 @@ impl InnerEvmContext { /// /// Loading of accounts/storages is needed to make them warm. #[inline] - pub fn load_access_list(&mut self) -> Result<(), DB::Error> { + pub fn load_access_list(&mut self) -> Result<(), ::Error> { for AccessListItem { address, storage_keys, @@ -114,13 +118,16 @@ impl InnerEvmContext { /// Returns the error by replacing it with `Ok(())`, if any. #[inline] - pub fn take_error(&mut self) -> Result<(), DB::Error> { + pub fn take_error(&mut self) -> Result<(), ::Error> { core::mem::replace(&mut self.error, Ok(())) } /// Fetch block hash from database. #[inline] - pub fn block_hash(&mut self, number: u64) -> Result { + pub fn block_hash( + &mut self, + number: u64, + ) -> Result::Error> { self.db.block_hash(number) } @@ -132,7 +139,10 @@ impl InnerEvmContext { /// Loads an account into memory. Returns `true` if it is cold accessed. #[inline] - pub fn load_account(&mut self, address: Address) -> Result<(&mut Account, bool), DB::Error> { + pub fn load_account( + &mut self, + address: Address, + ) -> Result<(&mut Account, bool), ::Error> { self.journaled_state.load_account(address, &mut self.db) } @@ -140,14 +150,20 @@ impl InnerEvmContext { /// /// Return boolean pair where first is `is_cold` second bool `exists`. #[inline] - pub fn load_account_exist(&mut self, address: Address) -> Result { + pub fn load_account_exist( + &mut self, + address: Address, + ) -> Result::Error> { self.journaled_state .load_account_exist(address, &mut self.db) } /// Return account balance and is_cold flag. #[inline] - pub fn balance(&mut self, address: Address) -> Result<(U256, bool), DB::Error> { + pub fn balance( + &mut self, + address: Address, + ) -> Result<(U256, bool), ::Error> { self.journaled_state .load_account(address, &mut self.db) .map(|(acc, is_cold)| (acc.info.balance, is_cold)) @@ -157,7 +173,10 @@ impl InnerEvmContext { /// /// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code. #[inline] - pub fn code(&mut self, address: Address) -> Result<(Bytes, bool), DB::Error> { + pub fn code( + &mut self, + address: Address, + ) -> Result<(Bytes, bool), ::Error> { self.journaled_state .load_code(address, &mut self.db) .map(|(a, is_cold)| { @@ -176,7 +195,10 @@ impl InnerEvmContext { /// In case of EOF account it will return `EOF_MAGIC_HASH` /// (the hash of `0xEF00`). #[inline] - pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), DB::Error> { + pub fn code_hash( + &mut self, + address: Address, + ) -> Result<(B256, bool), ::Error> { let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?; if acc.is_empty() { return Ok((B256::ZERO, is_cold)); @@ -189,7 +211,11 @@ impl InnerEvmContext { /// Load storage slot, if storage is not present inside the account then it will be loaded from database. #[inline] - pub fn sload(&mut self, address: Address, index: U256) -> Result<(U256, bool), DB::Error> { + pub fn sload( + &mut self, + address: Address, + index: U256, + ) -> Result<(U256, bool), ::Error> { // account is always warm. reference on that statement https://eips.ethereum.org/EIPS/eip-2929 see `Note 2:` self.journaled_state.sload(address, index, &mut self.db) } @@ -201,7 +227,7 @@ impl InnerEvmContext { address: Address, index: U256, value: U256, - ) -> Result { + ) -> Result::Error> { self.journaled_state .sstore(address, index, value, &mut self.db) } @@ -224,7 +250,7 @@ impl InnerEvmContext { &mut self, address: Address, target: Address, - ) -> Result { + ) -> Result::Error> { self.journaled_state .selfdestruct(address, target, &mut self.db) } diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index febad10c08..16e61296ae 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -5,7 +5,6 @@ mod utils; #[cfg(feature = "alloydb")] mod alloydb; -pub mod emptydb; #[cfg(feature = "ethersdb")] mod ethersdb; pub mod in_memory_db; @@ -14,7 +13,7 @@ pub mod states; pub use crate::primitives::db::*; #[cfg(feature = "alloydb")] pub use alloydb::AlloyDB; -pub use emptydb::{EmptyDB, EmptyDBTyped}; +pub use crate::primitives::db::{EmptyDB, EmptyDBTyped}; #[cfg(feature = "ethersdb")] pub use ethersdb::EthersDB; pub use in_memory_db::*; diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 12cac0d7e8..fd8b456aa5 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -19,19 +19,19 @@ pub const CALL_STACK_LIMIT: u64 = 1024; /// EVM instance containing both internal EVM context and external context /// and the handler that dictates the logic of EVM (or hardfork specification). -pub struct Evm<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { +pub struct Evm<'a, EvmWiringT: EvmWiring> { /// Context of execution, containing both EVM and external context. - pub context: Context, + pub context: Context, /// Handler is a component of the of EVM that contains all the logic. Handler contains specification id /// and it different depending on the specified fork. - pub handler: Handler<'a, EvmWiringT, Context, EXT, DB>, + pub handler: Handler<'a, EvmWiringT, Context>, } -impl Debug for Evm<'_, EvmWiringT, EXT, DB> +impl Debug for Evm<'_, EvmWiringT> where - EvmWiringT: EvmWiring, - EXT: Debug, - DB: Database + Debug, + EvmWiringT: + EvmWiring, + ::Error: Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Evm") @@ -40,30 +40,28 @@ where } } -impl Evm<'_, EvmWiringT, EXT, DB> { +impl> Evm<'_, EvmWiringT> { /// Commit the changes to the database. - pub fn transact_commit( - &mut self, - ) -> EVMResultGeneric, EvmWiringT, DB::Error> { + pub fn transact_commit(&mut self) -> EVMResultGeneric, EvmWiringT> { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) } } -impl<'a> Evm<'a, EthereumWiring, (), EmptyDB> { +impl<'a> Evm<'a, EthereumWiring> { /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. - pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthereumWiring, (), EmptyDB> { + pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthereumWiring> { EvmBuilder::default() } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> Evm<'a, EvmWiringT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> { /// Create new EVM. pub fn new( - mut context: Context, - handler: Handler<'a, EvmWiringT, Context, EXT, DB>, - ) -> Evm<'a, EvmWiringT, EXT, DB> { + mut context: Context, + handler: Handler<'a, EvmWiringT, Context>, + ) -> Evm<'a, EvmWiringT> { context .evm .journaled_state @@ -73,7 +71,7 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> Evm<'a, EvmWiringT, EXT, DB> /// Allow for evm setting to be modified by feeding current evm /// into the builder for modifications. - pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { + pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { EvmBuilder::new(self) } @@ -82,7 +80,7 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> Evm<'a, EvmWiringT, EXT, DB> pub fn run_the_loop( &mut self, first_frame: Frame, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { let mut call_stack: Vec = Vec::with_capacity(1025); call_stack.push(first_frame); @@ -176,7 +174,7 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> Evm<'a, EvmWiringT, EXT, DB> } } -impl Evm<'_, EvmWiringT, EXT, DB> { +impl Evm<'_, EvmWiringT> { /// Returns specification (hardfork) that the EVM is instanced with. /// /// SpecId depends on the handler. @@ -187,7 +185,7 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// Pre verify transaction by checking Environment, initial gas spend and if caller /// has enough balance to pay for the gas. #[inline] - pub fn preverify_transaction(&mut self) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + pub fn preverify_transaction(&mut self) -> EVMResultGeneric<(), EvmWiringT> { let output = self.preverify_transaction_inner().map(|_| ()); self.clear(); output @@ -202,7 +200,7 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// /// This function will not validate the transaction. #[inline] - pub fn transact_preverified(&mut self) -> EVMResult { + pub fn transact_preverified(&mut self) -> EVMResult { let initial_gas_spend = self .handler .validation() @@ -219,7 +217,7 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// Pre verify transaction inner. #[inline] - fn preverify_transaction_inner(&mut self) -> EVMResultGeneric { + fn preverify_transaction_inner(&mut self) -> EVMResultGeneric { self.handler.validation().env(&self.context.evm.env)?; let initial_gas_spend = self .handler @@ -235,7 +233,7 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// /// This function will validate the transaction. #[inline] - pub fn transact(&mut self) -> EVMResult { + pub fn transact(&mut self) -> EVMResult { let initial_gas_spend = self.preverify_transaction_inner().map_err(|e| { self.clear(); e @@ -273,13 +271,13 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// Returns the reference of database #[inline] - pub fn db(&self) -> &DB { + pub fn db(&self) -> &EvmWiringT::Database { &self.context.evm.db } /// Returns the mutable reference of database #[inline] - pub fn db_mut(&mut self) -> &mut DB { + pub fn db_mut(&mut self) -> &mut EvmWiringT::Database { &mut self.context.evm.db } @@ -297,13 +295,15 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// Returns internal database and external struct. #[inline] - pub fn into_context(self) -> Context { + pub fn into_context(self) -> Context { self.context } /// Returns database and [`EnvWithEvmWiring`]. #[inline] - pub fn into_db_and_env_with_handler_cfg(self) -> (DB, EnvWithEvmWiring) { + pub fn into_db_and_env_with_handler_cfg( + self, + ) -> (EvmWiringT::Database, EnvWithEvmWiring) { ( self.context.evm.inner.db, EnvWithEvmWiring { @@ -315,15 +315,12 @@ impl Evm<'_, EvmWiringT, EXT, DB> { /// Returns [Context] and hardfork. #[inline] - pub fn into_context_with_spec_id(self) -> ContextWithEvmWiring { + pub fn into_context_with_spec_id(self) -> ContextWithEvmWiring { ContextWithEvmWiring::new(self.context, self.handler.spec_id) } /// Transact pre-verified transaction. - fn transact_preverified_inner( - &mut self, - initial_gas_spend: u64, - ) -> EVMResult { + fn transact_preverified_inner(&mut self, initial_gas_spend: u64) -> EVMResult { let spec_id = self.spec_id(); let ctx = &mut self.context; let pre_exec = self.handler.pre_execution(); diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 471e27237e..02aba1de22 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -11,9 +11,7 @@ pub use handle_types::*; // Includes. use crate::{ interpreter::{opcode::InstructionTables, Host, InterpreterAction, SharedMemory}, - primitives::{ - db::Database, spec_to_generic, EVMResultGeneric, InvalidTransaction, TransactionValidation, - }, + primitives::{spec_to_generic, EVMResultGeneric, InvalidTransaction, TransactionValidation}, Context, EvmWiring, Frame, }; use core::mem; @@ -25,28 +23,27 @@ use self::register::{HandleRegister, HandleRegisterBox}; /// Handler acts as a proxy and allow to define different behavior for different /// sections of the code. This allows nice integration of different chains or /// to disable some mainnet behavior. -pub struct Handler<'a, EvmWiringT: EvmWiring, H: Host + 'a, EXT, DB: Database> { +pub struct Handler<'a, EvmWiringT: EvmWiring, H: Host + 'a> { /// Handler hardfork pub spec_id: EvmWiringT::Hardfork, /// Instruction table type. pub instruction_table: InstructionTables<'a, H>, /// Registers that will be called on initialization. - pub registers: Vec>, + pub registers: Vec>, /// Validity handles. - pub validation: ValidationHandler<'a, EvmWiringT, EXT, DB>, + pub validation: ValidationHandler<'a, EvmWiringT>, /// Pre execution handle. - pub pre_execution: PreExecutionHandler<'a, EvmWiringT, EXT, DB>, + pub pre_execution: PreExecutionHandler<'a, EvmWiringT>, /// Post Execution handle. - pub post_execution: PostExecutionHandler<'a, EvmWiringT, EXT, DB>, + pub post_execution: PostExecutionHandler<'a, EvmWiringT>, /// Execution loop that handles frames. - pub execution: ExecutionHandler<'a, EvmWiringT, EXT, DB>, + pub execution: ExecutionHandler<'a, EvmWiringT>, } -impl<'a, EvmWiringT, EXT, DB> EvmHandler<'a, EvmWiringT, EXT, DB> +impl<'a, EvmWiringT> EvmHandler<'a, EvmWiringT> where EvmWiringT: EvmWiring>>, - DB: Database, { /// Creates a base/vanilla Ethereum handler with the provided spec id. pub fn mainnet_with_spec(spec_id: EvmWiringT::Hardfork) -> Self { @@ -65,11 +62,7 @@ where } } -impl<'a, EvmWiringT, EXT, DB> EvmHandler<'a, EvmWiringT, EXT, DB> -where - EvmWiringT: EvmWiring, - DB: Database, -{ +impl<'a, EvmWiringT: EvmWiring> EvmHandler<'a, EvmWiringT> { /// Returns the specification ID. pub fn spec_id(&self) -> EvmWiringT::Hardfork { self.spec_id @@ -80,16 +73,14 @@ where &self, frame: &mut Frame, shared_memory: &mut SharedMemory, - context: &mut Context, - ) -> EVMResultGeneric { + context: &mut Context, + ) -> EVMResultGeneric { self.execution .execute_frame(frame, shared_memory, &self.instruction_table, context) } /// Take instruction table. - pub fn take_instruction_table( - &mut self, - ) -> InstructionTables<'a, Context> { + pub fn take_instruction_table(&mut self) -> InstructionTables<'a, Context> { let spec_id = self.spec_id(); mem::replace( &mut self.instruction_table, @@ -98,67 +89,56 @@ where } /// Set instruction table. - pub fn set_instruction_table( - &mut self, - table: InstructionTables<'a, Context>, - ) { + pub fn set_instruction_table(&mut self, table: InstructionTables<'a, Context>) { self.instruction_table = table; } /// Returns reference to pre execution handler. - pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EvmWiringT, EXT, DB> { + pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EvmWiringT> { &self.pre_execution } /// Returns reference to pre execution handler. - pub fn post_execution(&self) -> &PostExecutionHandler<'a, EvmWiringT, EXT, DB> { + pub fn post_execution(&self) -> &PostExecutionHandler<'a, EvmWiringT> { &self.post_execution } /// Returns reference to frame handler. - pub fn execution(&self) -> &ExecutionHandler<'a, EvmWiringT, EXT, DB> { + pub fn execution(&self) -> &ExecutionHandler<'a, EvmWiringT> { &self.execution } /// Returns reference to validation handler. - pub fn validation(&self) -> &ValidationHandler<'a, EvmWiringT, EXT, DB> { + pub fn validation(&self) -> &ValidationHandler<'a, EvmWiringT> { &self.validation } /// Append handle register. - pub fn append_handler_register(&mut self, register: HandleRegisters<'a, EvmWiringT, EXT, DB>) { + pub fn append_handler_register(&mut self, register: HandleRegisters<'a, EvmWiringT>) { register.register(self); self.registers.push(register); } /// Append plain handle register. - pub fn append_handler_register_plain(&mut self, register: HandleRegister) { + pub fn append_handler_register_plain(&mut self, register: HandleRegister) { register(self); self.registers.push(HandleRegisters::Plain(register)); } /// Append boxed handle register. - pub fn append_handler_register_box( - &mut self, - register: HandleRegisterBox<'a, EvmWiringT, EXT, DB>, - ) { + pub fn append_handler_register_box(&mut self, register: HandleRegisterBox<'a, EvmWiringT>) { register(self); self.registers.push(HandleRegisters::Box(register)); } } -impl<'a, EvmWiringT, EXT, DB> EvmHandler<'a, EvmWiringT, EXT, DB> -where - EvmWiringT: - EvmWiring>>, - DB: Database, -{ +impl<'a, EvmWiringT: EvmWiring> EvmHandler<'a, EvmWiringT> { /// Pop last handle register and reapply all registers that are left. - pub fn pop_handle_register(&mut self) -> Option> { + pub fn pop_handle_register(&mut self) -> Option> { let out = self.registers.pop(); if out.is_some() { let registers = core::mem::take(&mut self.registers); - let mut base_handler = EvmWiringT::handler::<'a, EXT, DB>(self.spec_id); + let mut base_handler = EvmWiringT::handler::<'a>(self.spec_id); // apply all registers to default handler and raw mainnet instruction table. for register in registers { base_handler.append_handler_register(register) @@ -176,7 +156,7 @@ where let registers = core::mem::take(&mut self.registers); // register for optimism is added as a register, so we need to create mainnet handler here. - let mut handler = EvmWiringT::handler::<'a, EXT, DB>(spec_id); + let mut handler = EvmWiringT::handler::<'a>(spec_id); // apply all registers to default handler and raw mainnet instruction table. for register in registers { handler.append_handler_register(register) @@ -198,21 +178,19 @@ mod test { use super::*; - type TestEvmWiring = primitives::EthereumWiring; + type TestEvmWiring = primitives::EthereumWiring; #[test] fn test_handler_register_pop() { - let register = - |inner: &Rc>| -> HandleRegisterBox<'_, TestEvmWiring, (), EmptyDB> { - let inner = inner.clone(); - Box::new(move |h| { - *inner.borrow_mut() += 1; - h.post_execution.output = - Arc::new(|_, _| Err(EVMError::Custom("test".to_string()))) - }) - }; - - let mut handler = EvmHandler::<'_, TestEvmWiring, (), EmptyDB>::mainnet_with_spec( + let register = |inner: &Rc>| -> HandleRegisterBox<'_, TestEvmWiring> { + let inner = inner.clone(); + Box::new(move |h| { + *inner.borrow_mut() += 1; + h.post_execution.output = Arc::new(|_, _| Err(EVMError::Custom("test".to_string()))) + }) + }; + + let mut handler = EvmHandler::<'_, TestEvmWiring>::mainnet_with_spec( ::Hardfork::default(), ); let test = Rc::new(RefCell::new(0)); diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index 271e7bac48..d5d3fbc86c 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -2,7 +2,7 @@ use crate::{ frame::EOFCreateFrame, handler::mainnet, interpreter::{CallInputs, CreateInputs, SharedMemory}, - primitives::{db::Database, EVMResultGeneric, Spec}, + primitives::{EVMResultGeneric, Spec}, CallFrame, Context, CreateFrame, EvmWiring, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ @@ -12,171 +12,154 @@ use revm_interpreter::{ use std::{boxed::Box, sync::Arc}; /// Handles first frame return handle. -pub type LastFrameReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - &mut FrameResult, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> - + 'a, +pub type LastFrameReturnHandle<'a, EvmWiringT> = Arc< + dyn Fn(&mut Context, &mut FrameResult) -> EVMResultGeneric<(), EvmWiringT> + 'a, >; /// Executes a single frame. Errors can be returned in the EVM context. -pub type ExecuteFrameHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type ExecuteFrameHandle<'a, EvmWiringT> = Arc< dyn Fn( &mut Frame, &mut SharedMemory, - &InstructionTables<'_, Context>, - &mut Context, - ) -> EVMResultGeneric::Error> + &InstructionTables<'_, Context>, + &mut Context, + ) -> EVMResultGeneric + 'a, >; /// Handle sub call. -pub type FrameCallHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - Box, - ) -> EVMResultGeneric::Error> +pub type FrameCallHandle<'a, EvmWiringT> = Arc< + dyn Fn(&mut Context, Box) -> EVMResultGeneric + 'a, >; /// Handle call return -pub type FrameCallReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type FrameCallReturnHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric + 'a, >; /// Insert call outcome to the parent -pub type InsertCallOutcomeHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type InsertCallOutcomeHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, &mut Frame, &mut SharedMemory, CallOutcome, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> + ) -> EVMResultGeneric<(), EvmWiringT> + 'a, >; /// Handle sub create. -pub type FrameCreateHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type FrameCreateHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric + 'a, >; /// Handle create return -pub type FrameCreateReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type FrameCreateReturnHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric + 'a, >; /// Insert call outcome to the parent -pub type InsertCreateOutcomeHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - &mut Frame, - CreateOutcome, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> +pub type InsertCreateOutcomeHandle<'a, EvmWiringT> = Arc< + dyn Fn(&mut Context, &mut Frame, CreateOutcome) -> EVMResultGeneric<(), EvmWiringT> + 'a, >; /// Handle EOF sub create. -pub type FrameEOFCreateHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type FrameEOFCreateHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric + 'a, >; /// Handle EOF create return -pub type FrameEOFCreateReturnHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type FrameEOFCreateReturnHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, Box, InterpreterResult, - ) -> EVMResultGeneric::Error> + ) -> EVMResultGeneric + 'a, >; /// Insert EOF crate outcome to the parent -pub type InsertEOFCreateOutcomeHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - &mut Frame, - CreateOutcome, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> +pub type InsertEOFCreateOutcomeHandle<'a, EvmWiringT> = Arc< + dyn Fn(&mut Context, &mut Frame, CreateOutcome) -> EVMResultGeneric<(), EvmWiringT> + 'a, >; /// Handles related to stack frames. -pub struct ExecutionHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { +pub struct ExecutionHandler<'a, EvmWiringT: EvmWiring> { /// Handles last frame return, modified gas for refund and /// sets tx gas limit. - pub last_frame_return: LastFrameReturnHandle<'a, EvmWiringT, EXT, DB>, + pub last_frame_return: LastFrameReturnHandle<'a, EvmWiringT>, /// Executes a single frame. - pub execute_frame: ExecuteFrameHandle<'a, EvmWiringT, EXT, DB>, + pub execute_frame: ExecuteFrameHandle<'a, EvmWiringT>, /// Frame call - pub call: FrameCallHandle<'a, EvmWiringT, EXT, DB>, + pub call: FrameCallHandle<'a, EvmWiringT>, /// Call return - pub call_return: FrameCallReturnHandle<'a, EvmWiringT, EXT, DB>, + pub call_return: FrameCallReturnHandle<'a, EvmWiringT>, /// Insert call outcome - pub insert_call_outcome: InsertCallOutcomeHandle<'a, EvmWiringT, EXT, DB>, + pub insert_call_outcome: InsertCallOutcomeHandle<'a, EvmWiringT>, /// Frame crate - pub create: FrameCreateHandle<'a, EvmWiringT, EXT, DB>, + pub create: FrameCreateHandle<'a, EvmWiringT>, /// Crate return - pub create_return: FrameCreateReturnHandle<'a, EvmWiringT, EXT, DB>, + pub create_return: FrameCreateReturnHandle<'a, EvmWiringT>, /// Insert create outcome. - pub insert_create_outcome: InsertCreateOutcomeHandle<'a, EvmWiringT, EXT, DB>, + pub insert_create_outcome: InsertCreateOutcomeHandle<'a, EvmWiringT>, /// Frame EOFCreate - pub eofcreate: FrameEOFCreateHandle<'a, EvmWiringT, EXT, DB>, + pub eofcreate: FrameEOFCreateHandle<'a, EvmWiringT>, /// EOFCreate return - pub eofcreate_return: FrameEOFCreateReturnHandle<'a, EvmWiringT, EXT, DB>, + pub eofcreate_return: FrameEOFCreateReturnHandle<'a, EvmWiringT>, /// Insert EOFCreate outcome. - pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, EvmWiringT, EXT, DB>, + pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, EvmWiringT>, } -impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> - ExecutionHandler<'a, EvmWiringT, EXT, DB> -{ +impl<'a, EvmWiringT: EvmWiring + 'a> ExecutionHandler<'a, EvmWiringT> { /// Creates mainnet ExecutionHandler. pub fn new() -> Self { Self { - last_frame_return: Arc::new(mainnet::last_frame_return::), - execute_frame: Arc::new(mainnet::execute_frame::), - call: Arc::new(mainnet::call::), - call_return: Arc::new(mainnet::call_return::), + last_frame_return: Arc::new(mainnet::last_frame_return::), + execute_frame: Arc::new(mainnet::execute_frame::), + call: Arc::new(mainnet::call::), + call_return: Arc::new(mainnet::call_return::), insert_call_outcome: Arc::new(mainnet::insert_call_outcome), - create: Arc::new(mainnet::create::), - create_return: Arc::new(mainnet::create_return::), + create: Arc::new(mainnet::create::), + create_return: Arc::new(mainnet::create_return::), insert_create_outcome: Arc::new(mainnet::insert_create_outcome), - eofcreate: Arc::new(mainnet::eofcreate::), - eofcreate_return: Arc::new(mainnet::eofcreate_return::), + eofcreate: Arc::new(mainnet::eofcreate::), + eofcreate_return: Arc::new(mainnet::eofcreate_return::), insert_eofcreate_outcome: Arc::new(mainnet::insert_eofcreate_outcome), } } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWiringT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring> ExecutionHandler<'a, EvmWiringT> { /// Executes single frame. #[inline] pub fn execute_frame( &self, frame: &mut Frame, shared_memory: &mut SharedMemory, - instruction_tables: &InstructionTables<'_, Context>, - context: &mut Context, - ) -> EVMResultGeneric { + instruction_tables: &InstructionTables<'_, Context>, + context: &mut Context, + ) -> EVMResultGeneric { (self.execute_frame)(frame, shared_memory, instruction_tables, context) } @@ -184,9 +167,9 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn last_frame_return( &self, - context: &mut Context, + context: &mut Context, frame_result: &mut FrameResult, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT> { (self.last_frame_return)(context, frame_result) } @@ -194,9 +177,9 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn call( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.call)(context, inputs) } @@ -204,10 +187,10 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn call_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.call_return)(context, frame, interpreter_result) } @@ -215,11 +198,11 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn insert_call_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT> { (self.insert_call_outcome)(context, frame, shared_memory, outcome) } @@ -227,9 +210,9 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn create( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.create)(context, inputs) } @@ -237,10 +220,10 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn create_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.create_return)(context, frame, interpreter_result) } @@ -248,10 +231,10 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn insert_create_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT> { (self.insert_create_outcome)(context, frame, outcome) } @@ -259,9 +242,9 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn eofcreate( &self, - context: &mut Context, + context: &mut Context, inputs: Box, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.eofcreate)(context, inputs) } @@ -269,10 +252,10 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn eofcreate_return( &self, - context: &mut Context, + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> EVMResultGeneric { + ) -> EVMResultGeneric { (self.eofcreate_return)(context, frame, interpreter_result) } @@ -280,10 +263,10 @@ impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ExecutionHandler<'a, EvmWirin #[inline] pub fn insert_eofcreate_outcome( &self, - context: &mut Context, + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT> { (self.insert_eofcreate_outcome)(context, frame, outcome) } } diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index 3bb2a6f166..59bc29da0a 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -2,31 +2,24 @@ use crate::{ handler::mainnet, interpreter::Gas, - primitives::{db::Database, EVMResultGeneric, ResultAndState, Spec}, + primitives::{EVMResultGeneric, ResultAndState, Spec}, Context, EvmWiring, FrameResult, }; use std::sync::Arc; /// Reimburse the caller with ethereum it didn't spent. -pub type ReimburseCallerHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - &Gas, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> - + 'a, ->; +pub type ReimburseCallerHandle<'a, EvmWiringT> = + Arc, &Gas) -> EVMResultGeneric<(), EvmWiringT> + 'a>; /// Reward beneficiary with transaction rewards. -pub type RewardBeneficiaryHandle<'a, EvmWiringT, EXT, DB> = - ReimburseCallerHandle<'a, EvmWiringT, EXT, DB>; +pub type RewardBeneficiaryHandle<'a, EvmWiringT> = ReimburseCallerHandle<'a, EvmWiringT>; /// Main return handle, takes state from journal and transforms internal result to external. -pub type OutputHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type OutputHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, + &mut Context, FrameResult, - ) - -> EVMResultGeneric, EvmWiringT, ::Error> + ) -> EVMResultGeneric, EvmWiringT> + 'a, >; @@ -34,89 +27,86 @@ pub type OutputHandle<'a, EvmWiringT, EXT, DB> = Arc< /// This will be called after all the other handlers. /// /// It is useful for catching errors and returning them in a different way. -pub type EndHandle<'a, EvmWiringT, EXT, DB> = Arc< +pub type EndHandle<'a, EvmWiringT> = Arc< dyn Fn( - &mut Context, - EVMResultGeneric, EvmWiringT, ::Error>, - ) - -> EVMResultGeneric, EvmWiringT, ::Error> + &mut Context, + EVMResultGeneric, EvmWiringT>, + ) -> EVMResultGeneric, EvmWiringT> + 'a, >; /// Clear handle, doesn't have output, its purpose is to clear the /// context. It will always be called even on failed validation. -pub type ClearHandle<'a, EvmWiringT, EXT, DB> = Arc) + 'a>; +pub type ClearHandle<'a, EvmWiringT> = Arc) + 'a>; /// Handles related to post execution after the stack loop is finished. -pub struct PostExecutionHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { +pub struct PostExecutionHandler<'a, EvmWiringT: EvmWiring> { /// Reimburse the caller with ethereum it didn't spend. - pub reimburse_caller: ReimburseCallerHandle<'a, EvmWiringT, EXT, DB>, + pub reimburse_caller: ReimburseCallerHandle<'a, EvmWiringT>, /// Reward the beneficiary with caller fee. - pub reward_beneficiary: RewardBeneficiaryHandle<'a, EvmWiringT, EXT, DB>, + pub reward_beneficiary: RewardBeneficiaryHandle<'a, EvmWiringT>, /// Main return handle, returns the output of the transact. - pub output: OutputHandle<'a, EvmWiringT, EXT, DB>, + pub output: OutputHandle<'a, EvmWiringT>, /// Called when execution ends. /// End handle in comparison to output handle will be called every time after execution. /// Output in case of error will not be called. - pub end: EndHandle<'a, EvmWiringT, EXT, DB>, + pub end: EndHandle<'a, EvmWiringT>, /// Clear handle will be called always. In comparison to end that /// is called only on execution end, clear handle is called even if validation fails. - pub clear: ClearHandle<'a, EvmWiringT, EXT, DB>, + pub clear: ClearHandle<'a, EvmWiringT>, } -impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> - PostExecutionHandler<'a, EvmWiringT, EXT, DB> -{ +impl<'a, EvmWiringT: EvmWiring + 'a> PostExecutionHandler<'a, EvmWiringT> { /// Creates mainnet MainHandles. pub fn mainnet() -> Self { Self { - reimburse_caller: Arc::new(mainnet::reimburse_caller::), - reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), - output: Arc::new(mainnet::output::), - end: Arc::new(mainnet::end::), - clear: Arc::new(mainnet::clear::), + reimburse_caller: Arc::new(mainnet::reimburse_caller::), + reward_beneficiary: Arc::new(mainnet::reward_beneficiary::), + output: Arc::new(mainnet::output::), + end: Arc::new(mainnet::end::), + clear: Arc::new(mainnet::clear::), } } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> PostExecutionHandler<'a, EvmWiringT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring> PostExecutionHandler<'a, EvmWiringT> { /// Reimburse the caller with gas that were not spend. pub fn reimburse_caller( &self, - context: &mut Context, + context: &mut Context, gas: &Gas, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT> { (self.reimburse_caller)(context, gas) } /// Reward beneficiary pub fn reward_beneficiary( &self, - context: &mut Context, + context: &mut Context, gas: &Gas, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + ) -> EVMResultGeneric<(), EvmWiringT> { (self.reward_beneficiary)(context, gas) } /// Returns the output of transaction. pub fn output( &self, - context: &mut Context, + context: &mut Context, result: FrameResult, - ) -> EVMResultGeneric, EvmWiringT, DB::Error> { + ) -> EVMResultGeneric, EvmWiringT> { (self.output)(context, result) } /// End handler. pub fn end( &self, - context: &mut Context, - end_output: EVMResultGeneric, EvmWiringT, DB::Error>, - ) -> EVMResultGeneric, EvmWiringT, DB::Error> { + context: &mut Context, + end_output: EVMResultGeneric, EvmWiringT>, + ) -> EVMResultGeneric, EvmWiringT> { (self.end)(context, end_output) } /// Clean handler. - pub fn clear(&self, context: &mut Context) { + pub fn clear(&self, context: &mut Context) { (self.clear)(context) } } diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 30094637f7..8171fb8801 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -1,75 +1,65 @@ // Includes. use crate::{ handler::mainnet, - primitives::{db::Database, EVMResultGeneric, Spec}, + primitives::{EVMResultGeneric, Spec}, Context, ContextPrecompiles, EvmWiring, }; use std::sync::Arc; /// Loads precompiles into Evm -pub type LoadPrecompilesHandle<'a, EvmWiringT, DB> = - Arc ContextPrecompiles + 'a>; +pub type LoadPrecompilesHandle<'a, EvmWiringT> = + Arc ContextPrecompiles + 'a>; /// Load access list accounts and beneficiary. /// There is no need to load Caller as it is assumed that /// it will be loaded in DeductCallerHandle. -pub type LoadAccountsHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> - + 'a, ->; +pub type LoadAccountsHandle<'a, EvmWiringT> = + Arc) -> EVMResultGeneric<(), EvmWiringT> + 'a>; /// Deduct the caller to its limit. -pub type DeductCallerHandle<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> - + 'a, ->; +pub type DeductCallerHandle<'a, EvmWiringT> = + Arc) -> EVMResultGeneric<(), EvmWiringT> + 'a>; /// Handles related to pre execution before the stack loop is started. -pub struct PreExecutionHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { +pub struct PreExecutionHandler<'a, EvmWiringT: EvmWiring> { /// Load precompiles - pub load_precompiles: LoadPrecompilesHandle<'a, EvmWiringT, DB>, + pub load_precompiles: LoadPrecompilesHandle<'a, EvmWiringT>, /// Main load handle - pub load_accounts: LoadAccountsHandle<'a, EvmWiringT, EXT, DB>, + pub load_accounts: LoadAccountsHandle<'a, EvmWiringT>, /// Deduct max value from the caller. - pub deduct_caller: DeductCallerHandle<'a, EvmWiringT, EXT, DB>, + pub deduct_caller: DeductCallerHandle<'a, EvmWiringT>, } -impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> - PreExecutionHandler<'a, EvmWiringT, EXT, DB> -{ +impl<'a, EvmWiringT: EvmWiring + 'a> PreExecutionHandler<'a, EvmWiringT> { /// Creates mainnet MainHandles. pub fn new() -> Self { Self { - load_precompiles: Arc::new(mainnet::load_precompiles::), - load_accounts: Arc::new(mainnet::load_accounts::), - deduct_caller: Arc::new(mainnet::deduct_caller::), + load_precompiles: Arc::new(mainnet::load_precompiles::), + load_accounts: Arc::new(mainnet::load_accounts::), + deduct_caller: Arc::new(mainnet::deduct_caller::), } } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> PreExecutionHandler<'a, EvmWiringT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring> PreExecutionHandler<'a, EvmWiringT> { /// Deduct caller to its limit. pub fn deduct_caller( &self, - context: &mut Context, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + context: &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT> { (self.deduct_caller)(context) } /// Main load pub fn load_accounts( &self, - context: &mut Context, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + context: &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT> { (self.load_accounts)(context) } /// Load precompiles - pub fn load_precompiles(&self) -> ContextPrecompiles { + pub fn load_precompiles(&self) -> ContextPrecompiles { (self.load_precompiles)() } } diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index b1217d7db4..8884226283 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -1,76 +1,63 @@ use crate::{ handler::mainnet, - primitives::{ - db::Database, EVMResultGeneric, Env, InvalidTransaction, Spec, TransactionValidation, - }, + primitives::{EVMResultGeneric, Env, InvalidTransaction, Spec, TransactionValidation}, Context, EvmWiring, }; use std::sync::Arc; /// Handle that validates env. -pub type ValidateEnvHandle<'a, EvmWiringT, DB> = - Arc) -> EVMResultGeneric<(), EvmWiringT, ::Error> + 'a>; +pub type ValidateEnvHandle<'a, EvmWiringT> = + Arc) -> EVMResultGeneric<(), EvmWiringT> + 'a>; /// Handle that validates transaction environment against the state. /// Second parametar is initial gas. -pub type ValidateTxEnvAgainstState<'a, EvmWiringT, EXT, DB> = Arc< - dyn Fn( - &mut Context, - ) -> EVMResultGeneric<(), EvmWiringT, ::Error> - + 'a, ->; +pub type ValidateTxEnvAgainstState<'a, EvmWiringT> = + Arc) -> EVMResultGeneric<(), EvmWiringT> + 'a>; /// Initial gas calculation handle -pub type ValidateInitialTxGasHandle<'a, EvmWiringT, DB> = Arc< - dyn Fn(&Env) -> EVMResultGeneric::Error> + 'a, ->; +pub type ValidateInitialTxGasHandle<'a, EvmWiringT> = + Arc) -> EVMResultGeneric + 'a>; /// Handles related to validation. -pub struct ValidationHandler<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { +pub struct ValidationHandler<'a, EvmWiringT: EvmWiring> { /// Validate and calculate initial transaction gas. - pub initial_tx_gas: ValidateInitialTxGasHandle<'a, EvmWiringT, DB>, + pub initial_tx_gas: ValidateInitialTxGasHandle<'a, EvmWiringT>, /// Validate transactions against state data. - pub tx_against_state: ValidateTxEnvAgainstState<'a, EvmWiringT, EXT, DB>, + pub tx_against_state: ValidateTxEnvAgainstState<'a, EvmWiringT>, /// Validate Env. - pub env: ValidateEnvHandle<'a, EvmWiringT, DB>, + pub env: ValidateEnvHandle<'a, EvmWiringT>, } -impl<'a, EvmWiringT: EvmWiring, EXT: 'a, DB: Database + 'a> - ValidationHandler<'a, EvmWiringT, EXT, DB> +impl<'a, EvmWiringT: EvmWiring + 'a> ValidationHandler<'a, EvmWiringT> where ::ValidationError: From, { /// Create new ValidationHandles pub fn new() -> Self { Self { - initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), - env: Arc::new(mainnet::validate_env::), - tx_against_state: Arc::new( - mainnet::validate_tx_against_state::, - ), + initial_tx_gas: Arc::new(mainnet::validate_initial_tx_gas::), + env: Arc::new(mainnet::validate_env::), + tx_against_state: Arc::new(mainnet::validate_tx_against_state::), } } } -impl<'a, EvmWiringT: EvmWiring, EXT, DB: Database> ValidationHandler<'a, EvmWiringT, EXT, DB> { +impl<'a, EvmWiringT: EvmWiring> ValidationHandler<'a, EvmWiringT> { /// Validate env. - pub fn env(&self, env: &Env) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + pub fn env(&self, env: &Env) -> EVMResultGeneric<(), EvmWiringT> { (self.env)(env) } /// Initial gas - pub fn initial_tx_gas( - &self, - env: &Env, - ) -> EVMResultGeneric { + pub fn initial_tx_gas(&self, env: &Env) -> EVMResultGeneric { (self.initial_tx_gas)(env) } /// Validate ttansaction against the state. pub fn tx_against_state( &self, - context: &mut Context, - ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { + context: &mut Context, + ) -> EVMResultGeneric<(), EvmWiringT> { (self.tx_against_state)(context) } } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 1a2c044fdd..361704bdc1 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -1,5 +1,4 @@ use crate::{ - db::Database, frame::EOFCreateFrame, interpreter::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, @@ -17,12 +16,12 @@ use std::boxed::Box; /// Execute frame #[inline] -pub fn execute_frame( +pub fn execute_frame( frame: &mut Frame, shared_memory: &mut SharedMemory, - instruction_tables: &InstructionTables<'_, Context>, - context: &mut Context, -) -> EVMResultGeneric { + instruction_tables: &InstructionTables<'_, Context>, + context: &mut Context, +) -> EVMResultGeneric { let interpreter = frame.interpreter_mut(); let memory = mem::replace(shared_memory, EMPTY_SHARED_MEMORY); let next_action = match instruction_tables { @@ -73,29 +72,29 @@ pub fn frame_return_with_refund_flag( /// Handle output of the transaction #[inline] -pub fn last_frame_return( - context: &mut Context, +pub fn last_frame_return( + context: &mut Context, frame_result: &mut FrameResult, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { frame_return_with_refund_flag::(&context.evm.env, frame_result, true); Ok(()) } /// Handle frame sub call. #[inline] -pub fn call( - context: &mut Context, +pub fn call( + context: &mut Context, inputs: Box, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context.evm.make_call_frame(&inputs) } #[inline] -pub fn call_return( - context: &mut Context, +pub fn call_return( + context: &mut Context, frame: Box, interpreter_result: InterpreterResult, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context .evm .call_return(&interpreter_result, frame.frame_data.checkpoint); @@ -106,12 +105,12 @@ pub fn call_return( } #[inline] -pub fn insert_call_outcome( - context: &mut Context, +pub fn insert_call_outcome( + context: &mut Context, frame: &mut Frame, shared_memory: &mut SharedMemory, outcome: CallOutcome, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -123,10 +122,10 @@ pub fn insert_call_outcome( /// Handle frame sub create. #[inline] -pub fn create( - context: &mut Context, +pub fn create( + context: &mut Context, inputs: Box, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context .evm .make_create_frame(SPEC::SPEC_ID, &inputs) @@ -134,11 +133,11 @@ pub fn create( } #[inline] -pub fn create_return( - context: &mut Context, +pub fn create_return( + context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context.evm.create_return::( &mut interpreter_result, frame.created_address, @@ -151,11 +150,11 @@ pub fn create_return( } #[inline] -pub fn insert_create_outcome( - context: &mut Context, +pub fn insert_create_outcome( + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { context.evm.take_error().map_err(EVMError::Database)?; frame @@ -167,10 +166,10 @@ pub fn insert_create_outcome( /// Handle frame sub create. #[inline] -pub fn eofcreate( - context: &mut Context, +pub fn eofcreate( + context: &mut Context, inputs: Box, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context .evm .make_eofcreate_frame(SPEC::SPEC_ID, &inputs) @@ -178,11 +177,11 @@ pub fn eofcreate( } #[inline] -pub fn eofcreate_return( - context: &mut Context, +pub fn eofcreate_return( + context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> EVMResultGeneric { +) -> EVMResultGeneric { context.evm.eofcreate_return::( &mut interpreter_result, frame.created_address, @@ -195,11 +194,11 @@ pub fn eofcreate_return( } #[inline] -pub fn insert_eofcreate_outcome( - context: &mut Context, +pub fn insert_eofcreate_outcome( + context: &mut Context, frame: &mut Frame, outcome: CreateOutcome, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { core::mem::replace(&mut context.evm.error, Ok(())).map_err(EVMError::Database)?; frame @@ -212,13 +211,13 @@ pub fn insert_eofcreate_outcome( #[cfg(test)] mod tests { use super::*; - use crate::primitives::EthereumWiring; + use crate::primitives::DefaultEthereumWiring; use revm_interpreter::primitives::CancunSpec; use revm_precompile::Bytes; /// Creates frame result. fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { - let mut env = Env::::default(); + let mut env = Env::::default(); env.tx.gas_limit = 100; let mut first_frame = FrameResult::Call(CallOutcome::new( @@ -229,7 +228,11 @@ mod tests { }, 0..0, )); - frame_return_with_refund_flag::(&env, &mut first_frame, true); + frame_return_with_refund_flag::( + &env, + &mut first_frame, + true, + ); *first_frame.gas() } diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index 3bfb8299c8..45f6f01803 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,24 +1,24 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, Block, Bytecode, EVMError, EVMResultGeneric, ExecutionResult, ResultAndState, - Spec, SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, + Block, Bytecode, EVMError, EVMResultGeneric, ExecutionResult, ResultAndState, Spec, + SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, }, Context, EvmWiring, FrameResult, }; /// Mainnet end handle does not change the output. #[inline] -pub fn end( - _context: &mut Context, - evm_output: EVMResultGeneric, EvmWiringT, DB::Error>, -) -> EVMResultGeneric, EvmWiringT, DB::Error> { +pub fn end( + _context: &mut Context, + evm_output: EVMResultGeneric, EvmWiringT>, +) -> EVMResultGeneric, EvmWiringT> { evm_output } /// Clear handle clears error and journal state. #[inline] -pub fn clear(context: &mut Context) { +pub fn clear(context: &mut Context) { // clear error and journaled state. let _ = context.evm.take_error(); context.evm.inner.journaled_state.clear(); @@ -29,10 +29,10 @@ pub fn clear(context: &mut Context( - context: &mut Context, +pub fn reward_beneficiary( + context: &mut Context, gas: &Gas, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { let beneficiary = *context.evm.env.block.coinbase(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -61,10 +61,10 @@ pub fn reward_beneficiary( } #[inline] -pub fn reimburse_caller( - context: &mut Context, +pub fn reimburse_caller( + context: &mut Context, gas: &Gas, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { let caller = context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); @@ -86,10 +86,10 @@ pub fn reimburse_caller( /// Main return handle, returns the output of the transaction. #[inline] -pub fn output( - context: &mut Context, +pub fn output( + context: &mut Context, result: FrameResult, -) -> EVMResultGeneric, EvmWiringT, DB::Error> { +) -> EVMResultGeneric, EvmWiringT> { context.evm.take_error().map_err(EVMError::Database)?; // used gas with refund calculated. diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 90d409ab0c..959814e777 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -5,7 +5,7 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ - db::Database, Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction, + Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, EvmWiring, @@ -14,16 +14,15 @@ use std::vec::Vec; /// Main precompile load #[inline] -pub fn load_precompiles( -) -> ContextPrecompiles { +pub fn load_precompiles() -> ContextPrecompiles { ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) } /// Main load handle #[inline] -pub fn load_accounts( - context: &mut Context, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +pub fn load_accounts( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT> { // set journaling state flag. context.evm.journaled_state.set_spec_id(SPEC::SPEC_ID); @@ -154,9 +153,9 @@ pub fn deduct_caller_inner( /// Deducts the caller balance to the transaction limit. #[inline] -pub fn deduct_caller( - context: &mut Context, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +pub fn deduct_caller( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT> { // load caller's account. let (caller_account, _) = context .evm diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index d7db6058de..ca4879d8c2 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -2,16 +2,16 @@ use revm_interpreter::gas; use crate::{ primitives::{ - db::Database, EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, Transaction, + EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, Transaction, TransactionValidation, }, Context, EvmWiring, }; /// Validate environment for the mainnet. -pub fn validate_env( +pub fn validate_env( env: &Env, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> +) -> EVMResultGeneric<(), EvmWiringT> where ::ValidationError: From, { @@ -23,9 +23,9 @@ where } /// Validates transaction against the state. -pub fn validate_tx_against_state( - context: &mut Context, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> +pub fn validate_tx_against_state( + context: &mut Context, +) -> EVMResultGeneric<(), EvmWiringT> where ::ValidationError: From, { @@ -49,9 +49,9 @@ where } /// Validate initial transaction gas. -pub fn validate_initial_tx_gas( +pub fn validate_initial_tx_gas( env: &Env, -) -> EVMResultGeneric +) -> EVMResultGeneric where ::ValidationError: From, { diff --git a/crates/revm/src/handler/register.rs b/crates/revm/src/handler/register.rs index b151715843..f71d9b24f6 100644 --- a/crates/revm/src/handler/register.rs +++ b/crates/revm/src/handler/register.rs @@ -1,29 +1,26 @@ -use crate::{db::Database, handler::Handler, Context, EvmWiring}; +use crate::{handler::Handler, Context, EvmWiring}; use std::boxed::Box; /// EVM Handler -pub type EvmHandler<'a, EvmWiringT, EXT, DB> = - Handler<'a, EvmWiringT, Context, EXT, DB>; +pub type EvmHandler<'a, EvmWiringT> = Handler<'a, EvmWiringT, Context>; // Handle register -pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, EvmWiringT, EXT, DB>); +pub type HandleRegister = for<'a> fn(&mut EvmHandler<'a, EvmWiringT>); // Boxed handle register -pub type HandleRegisterBox<'a, EvmWiringT, EXT, DB> = - Box Fn(&mut EvmHandler<'e, EvmWiringT, EXT, DB>) + 'a>; +pub type HandleRegisterBox<'a, EvmWiringT> = + Box Fn(&mut EvmHandler<'e, EvmWiringT>) + 'a>; -pub enum HandleRegisters<'a, EvmWiringT: EvmWiring, EXT, DB: Database> { +pub enum HandleRegisters<'a, EvmWiringT: EvmWiring> { /// Plain function register - Plain(HandleRegister), + Plain(HandleRegister), /// Boxed function register. - Box(HandleRegisterBox<'a, EvmWiringT, EXT, DB>), + Box(HandleRegisterBox<'a, EvmWiringT>), } -impl<'register, EvmWiringT: EvmWiring, EXT, DB: Database> - HandleRegisters<'register, EvmWiringT, EXT, DB> -{ +impl<'register, EvmWiringT: EvmWiring> HandleRegisters<'register, EvmWiringT> { /// Call register function to modify EvmHandler. - pub fn register<'evm>(&self, handler: &mut EvmHandler<'evm, EvmWiringT, EXT, DB>) + pub fn register<'evm>(&self, handler: &mut EvmHandler<'evm, EvmWiringT>) where 'evm: 'register, { diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 2e588af785..657fb91aca 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -29,7 +29,7 @@ pub mod inspectors { /// EVM [Interpreter] callbacks. #[auto_impl(&mut, Box)] -pub trait Inspector { +pub trait Inspector { /// Called before the interpreter is initialized. /// /// If `interp.instruction_result` is set to anything other than [crate::interpreter::InstructionResult::Continue] then the execution of the interpreter @@ -38,7 +38,7 @@ pub trait Inspector { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { let _ = interp; let _ = context; @@ -53,7 +53,7 @@ pub trait Inspector { /// /// To get the current opcode, use `interp.current_opcode()`. #[inline] - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let _ = interp; let _ = context; } @@ -63,19 +63,14 @@ pub trait Inspector { /// Setting `interp.instruction_result` to anything other than [crate::interpreter::InstructionResult::Continue] alters the execution /// of the interpreter. #[inline] - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let _ = interp; let _ = context; } /// Called when a log is emitted. #[inline] - fn log( - &mut self, - interp: &mut Interpreter, - context: &mut EvmContext, - log: &Log, - ) { + fn log(&mut self, interp: &mut Interpreter, context: &mut EvmContext, log: &Log) { let _ = interp; let _ = context; let _ = log; @@ -87,7 +82,7 @@ pub trait Inspector { #[inline] fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut CallInputs, ) -> Option { let _ = context; @@ -103,7 +98,7 @@ pub trait Inspector { #[inline] fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -120,7 +115,7 @@ pub trait Inspector { #[inline] fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { let _ = context; @@ -135,7 +130,7 @@ pub trait Inspector { #[inline] fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -149,7 +144,7 @@ pub trait Inspector { /// This can happen from create TX or from EOFCREATE opcode. fn eofcreate( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &mut EOFCreateInputs, ) -> Option { let _ = context; @@ -160,7 +155,7 @@ pub trait Inspector { /// Called when eof creating has ended. fn eofcreate_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &EOFCreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index 87de94df0a..ed73545b95 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -20,18 +20,18 @@ pub struct CustomPrintTracer { gas_inspector: GasInspector, } -impl Inspector for CustomPrintTracer { +impl Inspector for CustomPrintTracer { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { self.gas_inspector.initialize_interp(interp, context); } // 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, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { let opcode = interp.current_opcode(); let name = OpCode::name_by_op(opcode); @@ -56,13 +56,13 @@ impl Inspector for CustomPr self.gas_inspector.step(interp, context); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); } fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -71,7 +71,7 @@ impl Inspector for CustomPr fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { @@ -80,7 +80,7 @@ impl Inspector for CustomPr fn call( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, inputs: &mut CallInputs, ) -> Option { println!( @@ -97,7 +97,7 @@ impl Inspector for CustomPr fn create( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, inputs: &mut CreateInputs, ) -> Option { println!( diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 550dd94b73..b1da062f70 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -165,7 +165,7 @@ impl TracerEip3155 { fn print_summary( &mut self, result: &InterpreterResult, - context: &mut EvmContext, + context: &mut EvmContext, ) { if self.print_summary { let spec_name: &str = context.spec_id().into(); @@ -184,16 +184,16 @@ impl TracerEip3155 { } } -impl Inspector for TracerEip3155 { +impl Inspector for TracerEip3155 { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { self.gas_inspector.initialize_interp(interp, context); } - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step(interp, context); self.stack.clone_from(interp.stack.data()); self.memory = if self.include_memory { @@ -208,7 +208,7 @@ impl Inspector for TracerEi self.refunded = interp.gas.refunded(); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); if self.skip { self.skip = false; @@ -241,7 +241,7 @@ impl Inspector for TracerEi fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -258,7 +258,7 @@ impl Inspector for TracerEi fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 4468c817ad..738b34a248 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -26,11 +26,11 @@ impl GasInspector { } } -impl Inspector for GasInspector { +impl Inspector for GasInspector { fn initialize_interp( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.gas_remaining = interp.gas.limit(); } @@ -38,7 +38,7 @@ impl Inspector for GasInspe fn step( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { self.gas_remaining = interp.gas.remaining(); } @@ -46,7 +46,7 @@ impl Inspector for GasInspe fn step_end( &mut self, interp: &mut crate::interpreter::Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { let remaining = interp.gas.remaining(); self.last_gas_cost = self.gas_remaining.saturating_sub(remaining); @@ -55,7 +55,7 @@ impl Inspector for GasInspe fn call_end( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, _inputs: &CallInputs, mut outcome: CallOutcome, ) -> CallOutcome { @@ -68,7 +68,7 @@ impl Inspector for GasInspe fn create_end( &mut self, - _context: &mut EvmContext, + _context: &mut EvmContext, _inputs: &CreateInputs, mut outcome: CreateOutcome, ) -> CreateOutcome { @@ -89,7 +89,7 @@ mod tests { primitives::{self, Log}, }; - type TestEvmWiring = primitives::EthereumWiring; + type TestEvmWiring = primitives::DefaultEthereumWiring; #[derive(Default, Debug)] struct StackInspector { @@ -98,16 +98,16 @@ mod tests { gas_remaining_steps: Vec<(usize, u64)>, } - impl Inspector for StackInspector { + impl Inspector for StackInspector { fn initialize_interp( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, ) { self.gas_inspector.initialize_interp(interp, context); } - fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.pc = interp.program_counter(); self.gas_inspector.step(interp, context); } @@ -115,13 +115,13 @@ mod tests { fn log( &mut self, interp: &mut Interpreter, - context: &mut EvmContext, + context: &mut EvmContext, log: &Log, ) { self.gas_inspector.log(interp, context, log); } - fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext) { self.gas_inspector.step_end(interp, context); self.gas_remaining_steps .push((self.pc, self.gas_inspector.gas_remaining())); @@ -129,7 +129,7 @@ mod tests { fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, call: &mut CallInputs, ) -> Option { self.gas_inspector.call(context, call) @@ -137,7 +137,7 @@ mod tests { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -146,7 +146,7 @@ mod tests { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, call: &mut CreateInputs, ) -> Option { self.gas_inspector.create(context, call); @@ -155,7 +155,7 @@ mod tests { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index ec9883029c..6be3f35777 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -10,16 +10,14 @@ use revm_interpreter::opcode::DynInstruction; use std::{rc::Rc, sync::Arc, vec::Vec}; /// Provides access to an `Inspector` instance. -pub trait GetInspector { +pub trait GetInspector { /// Returns the associated `Inspector`. - fn get_inspector(&mut self) -> &mut impl Inspector; + fn get_inspector(&mut self) -> &mut impl Inspector; } -impl> - GetInspector for INSP -{ +impl> GetInspector for INSP { #[inline] - fn get_inspector(&mut self) -> &mut impl Inspector { + fn get_inspector(&mut self) -> &mut impl Inspector { self } } @@ -37,11 +35,9 @@ impl> /// and in case of Logs and Selfdestruct wrapper is wrapped again for the /// `log` and `selfdestruct` calls. pub fn inspector_handle_register< - EvmWiringT: EvmWiring, - DB: Database, - EXT: GetInspector, + EvmWiringT: EvmWiring>, >( - handler: &mut EvmHandler<'_, EvmWiringT, EXT, DB>, + handler: &mut EvmHandler<'_, EvmWiringT>, ) { let table = &mut handler.instruction_table; @@ -96,7 +92,7 @@ pub fn inspector_handle_register< let create_input_stack_inner = create_input_stack.clone(); let prev_handle = handler.execution.create.clone(); handler.execution.create = Arc::new( - move |ctx, mut inputs| -> EVMResultGeneric { + move |ctx, mut inputs| -> EVMResultGeneric { let inspector = ctx.external.get_inspector(); // call inspector create to change input or return outcome. if let Some(outcome) = inspector.create(&mut ctx.evm, &mut inputs) { @@ -223,14 +219,13 @@ pub fn inspector_handle_register< }); } -fn inspector_instruction( - prev: &DynInstruction<'_, Context>, +fn inspector_instruction( + prev: &DynInstruction<'_, Context>, interpreter: &mut Interpreter, - host: &mut Context, + host: &mut Context, ) where EvmWiringT: EvmWiring, - INSP: GetInspector, - DB: Database, + EvmWiringT::ExternalContext: GetInspector, { // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the // old Inspector behavior. @@ -265,7 +260,7 @@ mod tests { primitives, Evm, EvmContext, }; - type TestEvmWiring = primitives::EthereumWiring; + type TestEvmWiring = primitives::DefaultEthereumWiring; #[derive(Default, Debug)] struct StackInspector { @@ -276,11 +271,11 @@ mod tests { call_end: bool, } - impl Inspector for StackInspector { + impl Inspector for StackInspector { fn initialize_interp( &mut self, _interp: &mut Interpreter, - _context: &mut EvmContext, + _context: &mut EvmContext, ) { if self.initialize_interp_called { unreachable!("initialize_interp should not be called twice") @@ -288,21 +283,17 @@ mod tests { self.initialize_interp_called = true; } - fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { + fn step(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { self.step += 1; } - fn step_end( - &mut self, - _interp: &mut Interpreter, - _context: &mut EvmContext, - ) { + fn step_end(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext) { self.step_end += 1; } fn call( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _call: &mut CallInputs, ) -> Option { if self.call { @@ -315,7 +306,7 @@ mod tests { fn call_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _inputs: &CallInputs, outcome: CallOutcome, ) -> CallOutcome { @@ -329,7 +320,7 @@ mod tests { fn create( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _call: &mut CreateInputs, ) -> Option { assert_eq!(context.journaled_state.depth(), 0); @@ -338,7 +329,7 @@ mod tests { fn create_end( &mut self, - context: &mut EvmContext, + context: &mut EvmContext, _inputs: &CreateInputs, outcome: CreateOutcome, ) -> CreateOutcome { diff --git a/crates/revm/src/inspector/noop.rs b/crates/revm/src/inspector/noop.rs index 5395109d26..07a66c9c36 100644 --- a/crates/revm/src/inspector/noop.rs +++ b/crates/revm/src/inspector/noop.rs @@ -1,7 +1,7 @@ -use crate::{Database, EvmWiring, Inspector}; +use crate::{EvmWiring, Inspector}; /// Dummy [Inspector], helpful as standalone replacement. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NoOpInspector; -impl Inspector for NoOpInspector {} +impl Inspector for NoOpInspector {} diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 6a526a4499..e2971af309 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -85,7 +85,7 @@ pub fn validate_tx_against_state< EXT, DB: Database, >( - context: &mut Context, + context: &mut Context, ) -> Result<(), EVMError> { if context.evm.inner.env.tx.source_hash().is_some() { return Ok(()); @@ -96,7 +96,7 @@ pub fn validate_tx_against_state< /// Handle output of the transaction #[inline] pub fn last_frame_return( - context: &mut Context, + context: &mut Context, frame_result: &mut FrameResult, ) -> Result<(), EVMError> { let env = context.evm.inner.env(); @@ -184,7 +184,7 @@ pub fn load_precompiles( - context: &mut Context, + context: &mut Context, ) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { // the L1-cost fee is only computed for Optimism non-deposit transactions. @@ -203,7 +203,7 @@ fn load_accounts( - context: &mut Context, + context: &mut Context, ) -> Result<(), EVMError> { // load caller's account. let (caller_account, _) = context @@ -260,7 +260,7 @@ pub fn deduct_caller( - context: &mut Context, + context: &mut Context, gas: &Gas, ) -> Result<(), EVMError> { let is_deposit = context.evm.inner.env.tx.source_hash().is_some(); @@ -319,7 +319,7 @@ pub fn reward_beneficiary( - context: &mut Context, + context: &mut Context, frame_result: FrameResult, ) -> Result, EVMError> { let result = mainnet::output::(context, frame_result)?; @@ -341,7 +341,7 @@ pub fn output /// Deposit transaction can't be reverted and is always successful. #[inline] pub fn end( - context: &mut Context, + context: &mut Context, evm_output: Result, EVMError>, ) -> Result, EVMError> { evm_output.or_else(|err| { From 1c660da704e07aaa34172ea887c947becc167066 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 1 Aug 2024 16:41:26 +0200 Subject: [PATCH 37/59] some fixes --- crates/revm/src/builder.rs | 70 +++++++++---------- crates/revm/src/inspector.rs | 2 +- crates/revm/src/inspector/handler_register.rs | 2 +- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 44ce195629..e71c490ac9 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -18,6 +18,9 @@ pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring> { phantom: PhantomData, } +/// Zero stage of the builder +pub struct WiringStage; + /// First stage of the builder allows setting generic variables. /// Generic variables are database and external context. pub struct SetGenericStage; @@ -60,27 +63,24 @@ where } } -impl<'a, EvmWiringT, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, DB> +impl<'a, EvmWiringT> EvmBuilder<'a, SetGenericStage, EvmWiringT> where EvmWiringT: EvmWiring>>, { /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. - pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, EmptyDB> { + pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder { context: Context::new( self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: EvmWiringT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a>(self.handler.spec_id()), phantom: PhantomData, } } /// Sets the [`Database`] that will be used by [`Evm`]. - pub fn with_db( - self, - db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, ODB> { + pub fn with_db(self, db: ODB) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder { context: Context::new(self.context.evm.with_db(db), self.context.external), handler: EvmWiringT::handler::<'a, EXT, ODB>(self.handler.spec_id()), @@ -88,10 +88,10 @@ where } } /// Sets the [`DatabaseRef`] that will be used by [`Evm`]. - pub fn with_ref_db( + pub fn with_ref_db( self, db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { EvmBuilder { context: Context::new( self.context.evm.with_db(WrapDatabaseRef(db)), @@ -118,7 +118,7 @@ where pub fn with_env_with_handler_cfg( mut self, env_with_handler_cfg: EnvWithEvmWiring, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { let EnvWithEvmWiring { env, spec_id } = env_with_handler_cfg; self.context.evm.env = env; EvmBuilder { @@ -175,15 +175,13 @@ where EvmWiring>>, { /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. - pub fn reset_handler_with_empty_db( - self, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, EmptyDB> { + pub fn reset_handler_with_empty_db(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { EvmBuilder { context: Context::new( self.context.evm.with_db(EmptyDB::default()), self.context.external, ), - handler: EvmWiringT::handler::<'a, EXT, EmptyDB>(self.handler.spec_id()), + handler: EvmWiringT::handler::<'a>(self.handler.spec_id()), phantom: PhantomData, } } @@ -231,9 +229,7 @@ where } } -impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> - EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> -{ +impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWiringT> { /// This modifies the [EvmBuilder] to make it easy to construct an [`Evm`] with a _specific_ /// handler. /// @@ -252,8 +248,8 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> /// ``` pub fn with_handler( self, - handler: Handler<'a, EvmWiringT, Context, EXT, DB>, - ) -> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> { + handler: Handler<'a, EvmWiringT, Context>, + ) -> EvmBuilder<'a, BuilderStage, EvmWiringT> { EvmBuilder { context: self.context, handler, @@ -262,7 +258,7 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> } /// Builds the [`Evm`]. - pub fn build(self) -> Evm<'a, EvmWiringT, EXT, DB> { + pub fn build(self) -> Evm<'a, EvmWiringT> { Evm::new(self.context, self.handler) } @@ -272,8 +268,8 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. pub fn append_handler_register( mut self, - handle_register: register::HandleRegister, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { + handle_register: register::HandleRegister, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { self.handler .append_handler_register(register::HandleRegisters::Plain(handle_register)); EvmBuilder { @@ -290,8 +286,8 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> /// When called, EvmBuilder will transition from SetGenericStage to HandlerStage. pub fn append_handler_register_box( mut self, - handle_register: register::HandleRegisterBox<'a, EvmWiringT, EXT, DB>, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, EXT, DB> { + handle_register: register::HandleRegisterBox<'a, EvmWiringT>, + ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { self.handler .append_handler_register(register::HandleRegisters::Box(handle_register)); EvmBuilder { @@ -303,13 +299,16 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> } /// Allows modification of Evm Database. - pub fn modify_db(mut self, f: impl FnOnce(&mut DB)) -> Self { + pub fn modify_db(mut self, f: impl FnOnce(&mut EvmWiringT::Database)) -> Self { f(&mut self.context.evm.db); self } /// Allows modification of external context. - pub fn modify_external_context(mut self, f: impl FnOnce(&mut EXT)) -> Self { + pub fn modify_external_context( + mut self, + f: impl FnOnce(&mut EvmWiringT::ExternalContext), + ) -> Self { f(&mut self.context.external); self } @@ -357,10 +356,9 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring, EXT, DB: Database> } } -impl<'a, BuilderStage, EvmWiringT, EXT, DB> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT> EvmBuilder<'a, BuilderStage, EvmWiringT> where EvmWiringT: EvmWiring, - DB: Database, { /// Clears Block environment of EVM. pub fn with_clear_block_env(mut self) -> Self { @@ -369,10 +367,9 @@ where } } -impl<'a, BuilderStage, EvmWiringT, EXT, DB> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT> EvmBuilder<'a, BuilderStage, EvmWiringT> where EvmWiringT: EvmWiring, - DB: Database, { /// Clears Transaction environment of EVM. pub fn with_clear_tx_env(mut self) -> Self { @@ -381,10 +378,9 @@ where } } -impl<'a, BuilderStage, EvmWiringT, EXT, DB> EvmBuilder<'a, BuilderStage, EvmWiringT, EXT, DB> +impl<'a, BuilderStage, EvmWiringT> EvmBuilder<'a, BuilderStage, EvmWiringT> where EvmWiringT: EvmWiring, - DB: Database, { /// Clears Environment of EVM. pub fn with_clear_env(mut self) -> Self { @@ -417,8 +413,7 @@ where /// Resets [`Handler`] to default mainnet. pub fn reset_handler(mut self) -> Self { - self.handler = - EvmWiringT::::handler::<'a>(self.handler.spec_id()); + self.handler = EvmWiringT::handler::<'a>(self.handler.spec_id()); self } } @@ -475,8 +470,7 @@ mod test { // we need to use a box to capture the custom context in the instruction let custom_instruction = Box::new( - move |_interp: &mut Interpreter, - _host: &mut Context| { + move |_interp: &mut Interpreter, _host: &mut Context| { // modify the value let mut inner = custom_context.inner.borrow_mut(); *inner += 1; @@ -625,12 +619,12 @@ mod test { fn build_custom_precompile() { struct CustomPrecompile; - impl ContextStatefulPrecompile for CustomPrecompile { + impl ContextStatefulPrecompile for CustomPrecompile { fn call( &self, _input: &Bytes, _gas_limit: u64, - _context: &mut InnerEvmContext, + _context: &mut InnerEvmContext, ) -> PrecompileResult { Ok(PrecompileOutput::new(10, Bytes::new())) } diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 657fb91aca..b84c85b43c 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -12,7 +12,7 @@ use crate::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, }, - primitives::{db::Database, Address, Log, U256}, + primitives::{Address, Log, U256}, EvmContext, EvmWiring, }; use auto_impl::auto_impl; diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 6be3f35777..d597407244 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -219,7 +219,7 @@ pub fn inspector_handle_register< }); } -fn inspector_instruction( +fn inspector_instruction( prev: &DynInstruction<'_, Context>, interpreter: &mut Interpreter, host: &mut Context, From ed99ce9a2994d2968797dad0c38706b52a6f2e71 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 5 Aug 2024 10:59:40 +0200 Subject: [PATCH 38/59] temp --- crates/revm/src/builder.rs | 33 +++++++++++++++------------------ crates/revm/src/evm.rs | 6 +++--- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index e71c490ac9..879dc442a2 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,8 +1,8 @@ use crate::{ db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, - handler::{register, CfgEnvWithEvmWiring, EnvWithEvmWiring}, + handler::{register}, primitives::{self, CfgEnv, Env, EthereumWiring, InvalidTransaction, TransactionValidation}, - Context, ContextWithEvmWiring, Evm, EvmContext, EvmWiring, Handler, + Context, Evm, EvmContext, EvmWiring, Handler, }; use core::marker::PhantomData; use std::boxed::Box; @@ -11,7 +11,9 @@ use std::boxed::Box; /// Note that some of the methods that changes underlying structures /// will reset the registered handler to default mainnet. pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring> { - context: Context, + database: Option, + external_context: Option, + env: Option>>, /// Handler that will be used by EVM. It contains handle registers handler: Handler<'a, EvmWiringT, Context>, /// Phantom data to mark the stage of the builder. @@ -29,10 +31,12 @@ pub struct SetGenericStage; /// Requires the database and external context to be set. pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring> { +impl<'a> Default for EvmBuilder<'a, WiringStage, EthereumWiring> { fn default() -> Self { Self { - context: Context::default(), + database: None, + external_context: None, + env: None, handler: EthereumWiring::handler::<'a>( as primitives::EvmWiring>::Hardfork::default(), ), @@ -41,23 +45,16 @@ impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring } } -impl<'a, EvmWiringT> EvmBuilder<'a, SetGenericStage, EvmWiringT> -where - EvmWiringT: EvmWiring, +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { /// Sets the [`EvmWiring`] that will be used by [`Evm`]. - pub fn with_chain_spec(self) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> - where - NewEvmWiringT: EvmWiring< - Block: Default, - Transaction: Default + TransactionValidation>, - >, + pub fn new_wiring() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { - let Context { evm, external } = self.context; - EvmBuilder { - context: Context::new(EvmContext::new(evm.inner.db), external), - handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), + database: None, + external_context: None, + env: None, + handler: EvmWiringT::handler::<'a>(EvmWiringT::Hardfork::default()), phantom: PhantomData, } } diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index fd8b456aa5..4a037fb7fe 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -49,10 +49,10 @@ impl> Evm<'_, EvmWiringT> { } } -impl<'a> Evm<'a, EthereumWiring> { +impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> { /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. - pub fn builder() -> EvmBuilder<'a, SetGenericStage, EthereumWiring> { - EvmBuilder::default() + pub fn builder() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { + EvmBuilder::new_wiring() } } From 45c07c5a2a78f8332cac6ab3972625c25b095e04 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 5 Aug 2024 20:03:13 +0200 Subject: [PATCH 39/59] feat: make builder compile. EnvWiring and Result Halt --- Cargo.lock | 1 - bins/revm-test/src/bin/analysis.rs | 8 +- bins/revm-test/src/bin/burntpix/main.rs | 8 +- bins/revm-test/src/bin/snailtracer.rs | 6 +- bins/revm-test/src/bin/transfer.rs | 6 +- bins/revme/src/cmd/evmrunner.rs | 8 +- bins/revme/src/cmd/statetest/runner.rs | 36 +- crates/interpreter/src/host.rs | 8 +- crates/interpreter/src/host/dummy.rs | 9 +- .../interpreter/src/instructions/bitwise.rs | 2 +- .../interpreter/src/instructions/control.rs | 4 +- crates/interpreter/src/instructions/data.rs | 2 +- crates/interpreter/src/interpreter.rs | 5 +- .../interpreter/src/interpreter/contract.rs | 6 +- crates/primitives/Cargo.toml | 1 - crates/primitives/src/chain_spec.rs | 30 +- crates/primitives/src/env.rs | 38 +- crates/primitives/src/result.rs | 23 +- crates/revm/benches/bench.rs | 22 +- crates/revm/src/builder.rs | 753 +++++++++--------- crates/revm/src/chain_spec.rs | 3 +- crates/revm/src/context.rs | 6 +- crates/revm/src/context/evm_context.rs | 33 +- crates/revm/src/context/inner_evm_context.rs | 10 +- crates/revm/src/db.rs | 2 +- crates/revm/src/evm.rs | 37 +- crates/revm/src/handler/cfg.rs | 12 +- .../handler/handle_types/post_execution.rs | 26 +- .../src/handler/handle_types/validation.rs | 10 +- crates/revm/src/handler/mainnet/execution.rs | 6 +- .../src/handler/mainnet/post_execution.rs | 10 +- .../revm/src/handler/mainnet/pre_execution.rs | 4 +- crates/revm/src/handler/mainnet/validation.rs | 6 +- crates/revm/src/inspector/customprinter.rs | 10 +- crates/revm/src/inspector/eip3155.rs | 7 +- crates/revm/src/inspector/gas.rs | 8 +- crates/revm/src/inspector/handler_register.rs | 10 +- crates/revm/src/optimism/handler_register.rs | 2 +- 38 files changed, 615 insertions(+), 563 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e12676946..3f667e220e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3092,7 +3092,6 @@ dependencies = [ "bitvec", "c-kzg", "cfg-if", - "derive-where", "derive_more", "dyn-clone", "enumn", diff --git a/bins/revm-test/src/bin/analysis.rs b/bins/revm-test/src/bin/analysis.rs index a6fa92f46d..76978fe56c 100644 --- a/bins/revm-test/src/bin/analysis.rs +++ b/bins/revm-test/src/bin/analysis.rs @@ -1,11 +1,13 @@ use revm::{ db::BenchmarkDB, interpreter::analysis::to_analysed, - primitives::{address, bytes, Bytecode, Bytes, TxKind}, + primitives::{address, bytes, Bytecode, Bytes, EthereumWiring, TxKind}, Evm, }; use std::time::Instant; +type EthereumBenchmarkWire = EthereumWiring; + fn main() { let contract_data : Bytes = hex::decode( "6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820df254047bc8f2904ad3e966b6db116d703bebd40efadadb5e738c836ffc8f58a0029").unwrap().into(); @@ -13,7 +15,7 @@ fn main() { let bytecode_analysed = to_analysed(Bytecode::new_raw(contract_data)); // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::builder() + let mut evm = Evm::::builder() .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = address!("1000000000000000000000000000000000000000"); @@ -37,7 +39,7 @@ fn main() { let mut evm = evm .modify() - .reset_handler_with_db(BenchmarkDB::new_bytecode(bytecode_analysed)) + .with_db(BenchmarkDB::new_bytecode(bytecode_analysed)) .build(); let timer = Instant::now(); diff --git a/bins/revm-test/src/bin/burntpix/main.rs b/bins/revm-test/src/bin/burntpix/main.rs index ef0b78ea2a..bf170fa735 100644 --- a/bins/revm-test/src/bin/burntpix/main.rs +++ b/bins/revm-test/src/bin/burntpix/main.rs @@ -4,8 +4,8 @@ use regex::bytes::Regex; use revm::{ db::{CacheDB, EmptyDB}, primitives::{ - address, hex, keccak256, AccountInfo, Address, Bytecode, Bytes, ExecutionResult, Output, - TxKind, B256, U256, + address, hex, keccak256, AccountInfo, Address, Bytecode, Bytes, EthereumWiring, + ExecutionResult, Output, TxKind, B256, U256, }, Evm, }; @@ -28,6 +28,8 @@ sol! { } } +type EthereumBenchmarkWire = EthereumWiring, ()>; + fn main() { let (seed, iterations) = try_init_env_vars().expect("Failed to parse env vars"); @@ -35,7 +37,7 @@ fn main() { let db = init_db(); - let mut evm = Evm::builder() + let mut evm = Evm::::builder() .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); tx.transact_to = TxKind::Call(BURNTPIX_MAIN_ADDRESS); diff --git a/bins/revm-test/src/bin/snailtracer.rs b/bins/revm-test/src/bin/snailtracer.rs index cebe950a7f..53c662b790 100644 --- a/bins/revm-test/src/bin/snailtracer.rs +++ b/bins/revm-test/src/bin/snailtracer.rs @@ -1,15 +1,17 @@ use revm::{ db::BenchmarkDB, interpreter::analysis::to_analysed, - primitives::{address, bytes, Bytecode, Bytes, TxKind}, + primitives::{address, bytes, Bytecode, Bytes, EthereumWiring, TxKind}, Evm, }; +type EthereumBenchmarkWire = EthereumWiring; + pub fn simple_example() { let bytecode = to_analysed(Bytecode::new_raw(CONTRACT_DATA.clone())); // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::builder() + let mut evm = Evm::::builder() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. diff --git a/bins/revm-test/src/bin/transfer.rs b/bins/revm-test/src/bin/transfer.rs index 4fa1f29b09..a257d1df3e 100644 --- a/bins/revm-test/src/bin/transfer.rs +++ b/bins/revm-test/src/bin/transfer.rs @@ -1,14 +1,16 @@ use revm::{ db::BenchmarkDB, - primitives::{Bytecode, TxKind, U256}, + primitives::{Bytecode, EthereumWiring, TxKind, U256}, Evm, }; use std::time::Duration; +type EthereumBenchmarkWire = EthereumWiring; + fn main() { // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::builder() + let mut evm = Evm::::builder() .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index a8fd650a10..307502c827 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -2,7 +2,7 @@ use revm::{ db::BenchmarkDB, inspector_handle_register, inspectors::TracerEip3155, - primitives::{address, eof::EofDecodeError, Address, Bytecode, TxKind}, + primitives::{address, eof::EofDecodeError, Address, Bytecode, EthereumWiring, TxKind}, Database, Evm, }; use std::io::Error as IoError; @@ -80,7 +80,7 @@ impl Cmd { // BenchmarkDB is dummy state that implements Database trait. // the bytecode is deployed at zero address. - let mut evm = Evm::builder() + let mut evm = Evm::>::builder() .with_db(db) .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. @@ -105,9 +105,7 @@ impl Cmd { let out = if self.trace { let mut evm = evm .modify() - .reset_handler_with_external_context(TracerEip3155::new( - Box::new(std::io::stdout()), - )) + .with_external_context(TracerEip3155::new(Box::new(std::io::stdout()))) .append_handler_register(inspector_handle_register) .build(); diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 072dafc682..29358aee02 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -5,18 +5,18 @@ use super::{ }; use indicatif::{ProgressBar, ProgressDrawTarget}; use revm::{ - db::EmptyDB, + db::{EmptyDB, State}, inspector_handle_register, inspectors::TracerEip3155, primitives::{ - calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, Env, ExecutionResult, - SpecId, TxKind, B256, + calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, EnvWiring, + EthereumWiring, ExecutionResult, HaltReason, SpecId, TxKind, B256, }, - Evm, State, + Evm, }; use serde_json::json; use std::{ - convert::Infallible, + fmt::Debug, io::{stderr, stdout}, path::{Path, PathBuf}, sync::{ @@ -28,7 +28,8 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; -type TestEvmWiring = revm::primitives::EthereumWiring; +type ExecEvmWiring<'a> = revm::primitives::EthereumWiring<&'a mut State, ()>; +type TraceEvmWiring<'a> = revm::primitives::EthereumWiring<&'a mut State, TracerEip3155>; #[derive(Debug, Error)] #[error("Test {name} failed: {kind}")] @@ -128,12 +129,15 @@ fn skip_test(path: &Path) -> bool { ) || path_str.contains("stEOF") } -fn check_evm_execution( +fn check_evm_execution( test: &Test, expected_output: Option<&Bytes>, test_name: &str, - exec_result: &EVMResultGeneric, TestEvmWiring, Infallible>, - evm: &Evm<'_, TestEvmWiring, EXT, &mut State>, + exec_result: &EVMResultGeneric< + ExecutionResult, + EthereumWiring<&mut State, EXT>, + >, + evm: &Evm<'_, EthereumWiring<&mut State, EXT>>, print_json_outcome: bool, ) -> Result<(), TestError> { let logs_root = log_rlp_hash(exec_result.as_ref().map(|r| r.logs()).unwrap_or_default()); @@ -270,7 +274,7 @@ pub fn execute_test_suite( cache_state.insert_account_with_storage(address, acc_info, info.storage); } - let mut env = Box::>::default(); + let mut env = Box::>::default(); // for mainnet env.cfg.chain_id = 1; // env.cfg.spec_id is set down the road @@ -366,7 +370,7 @@ pub fn execute_test_suite( .with_cached_prestate(cache) .with_bundle_update() .build(); - let mut evm = Evm::builder() + let mut evm = Evm::::builder() .with_db(&mut state) .modify_env(|e| e.clone_from(&env)) .with_spec_id(spec_id) @@ -376,7 +380,8 @@ pub fn execute_test_suite( let (e, exec_result) = if trace { let mut evm = evm .modify() - .reset_handler_with_external_context( + .reset_handler_with_external_context::>() + .with_external_context( TracerEip3155::new(Box::new(stderr())).without_summary(), ) .append_handler_register(inspector_handle_register) @@ -428,17 +433,18 @@ pub fn execute_test_suite( // re build to run with tracing let mut cache = cache_state.clone(); cache.set_state_clear_flag(SpecId::enabled(spec_id, SpecId::SPURIOUS_DRAGON)); - let state = revm::db::State::builder() + let mut state = revm::db::State::builder() .with_cached_prestate(cache) .with_bundle_update() .build(); let path = path.display(); println!("\nTraces:"); - let mut evm = Evm::builder() + let mut evm = Evm::::builder() + .with_db(&mut state) .with_spec_id(spec_id) - .with_db(state) .with_env(env.clone()) + .reset_handler_with_external_context::>() .with_external_context(TracerEip3155::new(Box::new(stdout())).without_summary()) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 63f156224f..ab92723b5e 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -1,8 +1,8 @@ -use crate::primitives::{Address, Bytes, Env, Log, B256, U256}; +use crate::primitives::{Address, Bytes, Log, B256, U256}; mod dummy; pub use dummy::DummyHost; -use revm_primitives::EvmWiring; +use revm_primitives::{EnvWiring, EvmWiring}; /// EVM context host. pub trait Host { @@ -10,10 +10,10 @@ pub trait Host { type EvmWiringT: EvmWiring; /// Returns a reference to the environment. - fn env(&self) -> &Env; + fn env(&self) -> &EnvWiring; /// Returns a mutable reference to the environment. - fn env_mut(&mut self) -> &mut Env; + fn env_mut(&mut self) -> &mut EnvWiring; /// Load an account. /// diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 8438fae6c0..f6c49c0e2d 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,4 +1,5 @@ use derive_where::derive_where; +use revm_primitives::EnvWiring; use crate::{ primitives::{ @@ -16,7 +17,7 @@ pub struct DummyHost where EvmWiringT: EvmWiring, { - pub env: Env, + pub env: Env, pub storage: HashMap, pub transient_storage: HashMap, pub log: Vec, @@ -28,7 +29,7 @@ where { /// Create a new dummy host with the given [`Env`]. #[inline] - pub fn new(env: Env) -> Self { + pub fn new(env: EnvWiring) -> Self { Self { env, storage: HashMap::new(), @@ -52,12 +53,12 @@ where type EvmWiringT = EvmWiringT; #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &EnvWiring { &self.env } #[inline] - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut EnvWiring { &mut self.env } diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 9da8d77a44..c9f4ecb221 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -403,7 +403,7 @@ mod tests { expected: U256, } - let mut host = DummyHost::new(Env::::default()); + let mut host = DummyHost::::new(Env::default()); let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128); diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index ed593dedf0..5fdf025c18 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -206,7 +206,9 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { mod test { use std::sync::Arc; - use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, DefaultEthereumWiring, PragueSpec}; + use revm_primitives::{ + bytes, eof::TypesSection, Bytecode, DefaultEthereumWiring, Eof, PragueSpec, + }; use super::*; use crate::{ diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index f09d4ecd68..9cb315078e 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -83,7 +83,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { - use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, DefaultEthereumWiring, PragueSpec}; + use revm_primitives::{b256, bytes, Bytecode, Bytes, DefaultEthereumWiring, Eof, PragueSpec}; use std::sync::Arc; use super::*; diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 1533582bbd..2b796366f2 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -469,7 +469,7 @@ pub fn resize_memory(memory: &mut SharedMemory, gas: &mut Gas, new_size: usize) mod tests { use super::*; use crate::{opcode::InstructionTable, DummyHost}; - use revm_primitives::{CancunSpec, DefaultEthereumWiring, EthereumWiring}; + use revm_primitives::{CancunSpec, DefaultEthereumWiring}; #[test] fn object_safety() { @@ -477,7 +477,8 @@ mod tests { let mut host = crate::DummyHost::::default(); let table: &InstructionTable> = - &crate::opcode::make_instruction_table::, CancunSpec>(); + &crate::opcode::make_instruction_table::, CancunSpec>( + ); let _ = interp.run(EMPTY_SHARED_MEMORY, table, &mut host); let host: &mut dyn Host = diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index f4e19642d5..9a0db41152 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,8 +1,8 @@ -use revm_primitives::EvmWiring; +use revm_primitives::{EnvWiring, EvmWiring}; use super::analysis::to_analysed; use crate::{ - primitives::{Address, Bytecode, Bytes, Env, Transaction, TxKind, B256, U256}, + primitives::{Address, Bytecode, Bytes, Transaction, TxKind, B256, U256}, CallInputs, }; @@ -56,7 +56,7 @@ impl Contract { /// Creates a new contract from the given [`Env`]. #[inline] pub fn new_env( - env: &Env, + env: &EnvWiring, bytecode: Bytecode, hash: Option, ) -> Self { diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 85249dae59..65214c687f 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -43,7 +43,6 @@ kzg-rs = { version = "0.1", default-features = false, features = [ # utility enumn = "0.1" derive_more = { version = "0.99", optional = true } -derive-where = { version = "1.2.7", default-features = false } cfg-if = "1" dyn-clone = "1.0" diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/chain_spec.rs index 9ecfc1632b..17a55db64a 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/chain_spec.rs @@ -12,18 +12,20 @@ impl HardforkTrait for HardforkT where { } -cfg_if! { - if #[cfg(feature = "serde")] { - pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} - - impl HaltReasonTrait for HaltReasonT where - HaltReasonT: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} - } else { - pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From {} - impl HaltReasonTrait for HaltReasonT where - HaltReasonT: Clone + Debug + PartialEq + Eq + From {} - } +// cfg_if! { +// if #[cfg(feature = "serde")] { +// pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} + +// impl HaltReasonTrait for HaltReasonT where +// HaltReasonT: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} +// } else { +pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From {} +impl HaltReasonTrait for HaltReasonT where + HaltReasonT: Clone + Debug + PartialEq + Eq + From +{ } +// } +// } pub trait TransactionValidation { cfg_if! { @@ -37,10 +39,9 @@ pub trait TransactionValidation { } } - pub trait EvmWiring: Sized { /// External type - type ExternalContext: Sized; + type ExternalContext: Sized + Debug; /// Database type. type Database: Database; @@ -55,7 +56,6 @@ pub trait EvmWiring: Sized { /// Halt reason type. type HaltReason: HaltReasonTrait; - } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -63,7 +63,7 @@ pub struct EthereumWiring { phantom: core::marker::PhantomData<(DB, EXT)>, } -impl EvmWiring for EthereumWiring { +impl EvmWiring for EthereumWiring { type Database = DB; type ExternalContext = EXT; type Block = crate::BlockEnv; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 3761aa6b58..2d6026410a 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -13,42 +13,32 @@ use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; use core::fmt::Debug; use core::hash::Hash; -use derive_where::derive_where; use std::boxed::Box; use std::vec::Vec; +/// Subtype +pub type EnvWiring = + Env<::Block, ::Transaction>; + +#[derive(Clone, Debug, Default)] /// EVM environment configuration. -#[derive_where(Clone, Debug, Default; EvmWiringT::Block, EvmWiringT::Transaction)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Env { +pub struct Env { /// Configuration of the EVM itself. pub cfg: CfgEnv, /// Configuration of the block the transaction is in. - pub block: EvmWiringT::Block, + pub block: BlockT, /// Configuration of the transaction that is being executed. - pub tx: EvmWiringT::Transaction, + pub tx: TxT, } -impl Env { +impl Env { /// Create boxed [Env]. #[inline] - pub fn boxed(cfg: CfgEnv, block: EvmWiringT::Block, tx: EvmWiringT::Transaction) -> Box { + pub fn boxed(cfg: CfgEnv, block: BlockT, tx: TxT) -> Box { Box::new(Self { cfg, block, tx }) } - /// Transforms Evn to different Wiring with has same block and transaction. - pub fn into_evm_wiring< - OWiring: EvmWiring, - >( - self, - ) -> Env { - Env { - cfg: self.cfg, - block: self.block, - tx: self.tx, - } - } - /// Calculates the effective gas price of the transaction. #[inline] pub fn effective_gas_price(&self) -> U256 { @@ -277,7 +267,7 @@ impl Env { } } -impl> Env { +impl Env { /// Resets environment to default values. #[inline] pub fn clear(&mut self) { @@ -780,13 +770,11 @@ pub enum AnalysisKind { #[cfg(test)] mod tests { - use crate::{db::EmptyDB, EthereumWiring}; - use super::*; #[test] fn test_validate_tx_chain_id() { - let mut env = Env::>::default(); + let mut env = Env::::default(); env.tx.chain_id = Some(1); env.cfg.chain_id = 2; assert_eq!( @@ -797,7 +785,7 @@ mod tests { #[test] fn test_validate_tx_access_list() { - let mut env = Env::>::default(); + let mut env = Env::::default(); env.tx.access_list = vec![AccessListItem { address: Address::ZERO, storage_keys: vec![], diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 361f34359f..8e117ea17a 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,11 +1,13 @@ -use derive_where::derive_where; - -use crate::{db::Database, Address, Bytes, EvmState, EvmWiring, Log, TransactionValidation, U256}; +use crate::{ + db::Database, Address, Bytes, EvmState, EvmWiring, HaltReasonTrait, Log, TransactionValidation, + U256, +}; use core::fmt::{self, Debug}; use std::{boxed::Box, string::String, vec::Vec}; /// Result of EVM execution. -pub type EVMResult = EVMResultGeneric, EvmWiringT>; +pub type EVMResult = + EVMResultGeneric::HaltReason>, EvmWiringT>; /// Generic result of EVM execution. Used to represent error and generic output. pub type EVMResultGeneric = core::result::Result>; @@ -18,18 +20,17 @@ pub type EVMErrorForChain = EVMError< #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ResultAndState { +pub struct ResultAndState { /// Status of execution - pub result: ExecutionResult, + pub result: ExecutionResult, /// State that got updated pub state: EvmState, } /// Result of a transaction execution. -#[derive(Debug, PartialEq, Eq, Hash)] -#[derive_where(Clone; EvmWiringT::HaltReason)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum ExecutionResult { +pub enum ExecutionResult { /// Returned successfully Success { reason: SuccessReason, @@ -42,13 +43,13 @@ pub enum ExecutionResult { Revert { gas_used: u64, output: Bytes }, /// Reverted for various reasons and spend all gas. Halt { - reason: EvmWiringT::HaltReason, + reason: HaltReasonT, /// Halting will spend all the gas, and will be equal to gas_limit. gas_used: u64, }, } -impl ExecutionResult { +impl ExecutionResult { /// Returns if transaction execution is successful. /// 1 indicates success, 0 indicates revert. /// diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index 0c0cdcb682..22d49cc7f6 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -11,7 +11,7 @@ use revm_interpreter::{opcode::make_instruction_table, SharedMemory, EMPTY_SHARE use std::time::Duration; fn analysis(c: &mut Criterion) { - let evm = Evm::builder() + let evm = Evm::>::builder() .modify_tx_env(|tx| { tx.caller = address!("0000000000000000000000000000000000000002"); tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); @@ -29,16 +29,13 @@ fn analysis(c: &mut Criterion) { .sample_size(10); let raw = Bytecode::new_raw(contract_data.clone()); - let mut evm = evm - .modify() - .reset_handler_with_db(BenchmarkDB::new_bytecode(raw)) - .build(); + let mut evm = evm.modify().with_db(BenchmarkDB::new_bytecode(raw)).build(); bench_transact(&mut g, &mut evm); let analysed = to_analysed(Bytecode::new_raw(contract_data)); let mut evm = evm .modify() - .reset_handler_with_db(BenchmarkDB::new_bytecode(analysed)) + .with_db(BenchmarkDB::new_bytecode(analysed)) .build(); bench_transact(&mut g, &mut evm); @@ -46,7 +43,7 @@ fn analysis(c: &mut Criterion) { } fn snailtracer(c: &mut Criterion) { - let mut evm = Evm::builder() + let mut evm = Evm::>::builder() .with_db(BenchmarkDB::new_bytecode(bytecode(SNAILTRACER))) .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); @@ -66,7 +63,7 @@ fn snailtracer(c: &mut Criterion) { } fn transfer(c: &mut Criterion) { - let mut evm = Evm::builder() + let mut evm = Evm::>::builder() .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) .modify_tx_env(|tx| { tx.caller = address!("0000000000000000000000000000000000000001"); @@ -81,9 +78,9 @@ fn transfer(c: &mut Criterion) { g.finish(); } -fn bench_transact( +fn bench_transact( g: &mut BenchmarkGroup<'_, WallTime>, - evm: &mut Evm<'_, EthereumWiring, EXT, BenchmarkDB>, + evm: &mut Evm<'_, EthereumWiring>, ) { let state = match evm.context.evm.db.0 { Bytecode::LegacyRaw(_) => "raw", @@ -96,7 +93,7 @@ fn bench_transact( fn bench_eval( g: &mut BenchmarkGroup<'_, WallTime>, - evm: &mut Evm<'static, EthereumWiring, (), BenchmarkDB>, + evm: &mut Evm<'static, EthereumWiring>, ) { g.bench_function("eval", |b| { let contract = Contract { @@ -106,7 +103,8 @@ fn bench_eval( }; let mut shared_memory = SharedMemory::new(); let mut host = DummyHost::new(*evm.context.evm.env.clone()); - let instruction_table = make_instruction_table::, BerlinSpec>(); + let instruction_table = + make_instruction_table::>, BerlinSpec>(); b.iter(move || { // replace memory with empty memory to use it inside interpreter. // Later return memory back. diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 879dc442a2..52c9db7dc5 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,7 +1,9 @@ use crate::{ db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, - handler::{register}, - primitives::{self, CfgEnv, Env, EthereumWiring, InvalidTransaction, TransactionValidation}, + handler::register, + primitives::{ + self, CfgEnv, Env, EnvWiring, EthereumWiring, InvalidTransaction, TransactionValidation, + }, Context, Evm, EvmContext, EvmWiring, Handler, }; use core::marker::PhantomData; @@ -13,16 +15,13 @@ use std::boxed::Box; pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring> { database: Option, external_context: Option, - env: Option>>, + env: Option>>, /// Handler that will be used by EVM. It contains handle registers handler: Handler<'a, EvmWiringT, Context>, /// Phantom data to mark the stage of the builder. phantom: PhantomData, } -/// Zero stage of the builder -pub struct WiringStage; - /// First stage of the builder allows setting generic variables. /// Generic variables are database and external context. pub struct SetGenericStage; @@ -31,25 +30,15 @@ pub struct SetGenericStage; /// Requires the database and external context to be set. pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, WiringStage, EthereumWiring> { +impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring> { fn default() -> Self { - Self { - database: None, - external_context: None, - env: None, - handler: EthereumWiring::handler::<'a>( - as primitives::EvmWiring>::Hardfork::default(), - ), - phantom: PhantomData, - } + Self::new() } } -impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> -{ +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { /// Sets the [`EvmWiring`] that will be used by [`Evm`]. - pub fn new_wiring() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> - { + pub fn new() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder { database: None, external_context: None, @@ -58,172 +47,230 @@ impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> phantom: PhantomData, } } -} -impl<'a, EvmWiringT> EvmBuilder<'a, SetGenericStage, EvmWiringT> -where - EvmWiringT: - EvmWiring>>, -{ - /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. - pub fn with_empty_db(self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { - EvmBuilder { - context: Context::new( - self.context.evm.with_db(EmptyDB::default()), - self.context.external, - ), - handler: EvmWiringT::handler::<'a>(self.handler.spec_id()), - phantom: PhantomData, - } - } - /// Sets the [`Database`] that will be used by [`Evm`]. - pub fn with_db(self, db: ODB) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { - EvmBuilder { - context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: EvmWiringT::handler::<'a, EXT, ODB>(self.handler.spec_id()), - phantom: PhantomData, - } - } - /// Sets the [`DatabaseRef`] that will be used by [`Evm`]. - pub fn with_ref_db( - self, - db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { + pub fn new_with( + database: EvmWiringT::Database, + external_context: EvmWiringT::ExternalContext, + env: Box>, + handler: Handler<'a, EvmWiringT, Context>, + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder { - context: Context::new( - self.context.evm.with_db(WrapDatabaseRef(db)), - self.context.external, - ), - handler: EvmWiringT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), + database: Some(database), + external_context: Some(external_context), + env: Some(env), + handler, phantom: PhantomData, } } - /// Sets the external context that will be used by [`Evm`]. - pub fn with_external_context( + pub fn with_wiring( self, - external: OEXT, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, OEXT, DB> { + ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> { EvmBuilder { - context: Context::new(self.context.evm, external), - handler: EvmWiringT::handler::<'a, OEXT, DB>(self.handler.spec_id()), - phantom: PhantomData, - } - } - - /// Sets Builder with [`EnvWithEvmWiring`]. - pub fn with_env_with_handler_cfg( - mut self, - env_with_handler_cfg: EnvWithEvmWiring, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { - let EnvWithEvmWiring { env, spec_id } = env_with_handler_cfg; - self.context.evm.env = env; - EvmBuilder { - context: self.context, - handler: EvmWiringT::handler::<'a, EXT, DB>(spec_id), + database: None, + external_context: None, + env: None, + handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), phantom: PhantomData, } } - /// Sets Builder with [`ContextWithEvmWiring`]. - pub fn with_context_with_handler_cfg( + pub fn reset_handler_with_external_context< + NewEvmWiringT: EvmWiring< + Database = EvmWiringT::Database, + Block = EvmWiringT::Block, + Transaction = EvmWiringT::Transaction, + Hardfork = EvmWiringT::Hardfork, + HaltReason = EvmWiringT::HaltReason, + >, + >( self, - context_with_handler_cfg: ContextWithEvmWiring, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, OEXT, ODB> { + ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> { EvmBuilder { - context: context_with_handler_cfg.context, - handler: EvmWiringT::handler::<'a, OEXT, ODB>(context_with_handler_cfg.spec_id), + database: self.database, + external_context: None, + env: self.env, + // Handler that will be used by EVM. It contains handle registers + handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), phantom: PhantomData, } } - /// Sets Builder with [`CfgEnvWithEvmWiring`]. - pub fn with_cfg_env_with_handler_cfg( - mut self, - cfg_env_and_spec_id: CfgEnvWithEvmWiring, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { - self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; - + pub fn reset_new_database< + NewEvmWiringT: EvmWiring< + ExternalContext = EvmWiringT::ExternalContext, + Block = EvmWiringT::Block, + Transaction = EvmWiringT::Transaction, + Hardfork = EvmWiringT::Hardfork, + HaltReason = EvmWiringT::HaltReason, + >, + >( + self, + ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> { EvmBuilder { - context: self.context, - handler: EvmWiringT::handler::<'a>(cfg_env_and_spec_id.spec_id), - phantom: PhantomData, - } - } -} - -impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, HandlerStage, EvmWiringT> { - /// Creates new builder from Evm, Evm is consumed and all field are moved to Builder. - /// It will preserve set handler and context. - /// - /// Builder is in HandlerStage and both database and external are set. - pub fn new(evm: Evm<'a, EvmWiringT>) -> Self { - Self { - context: evm.context, - handler: evm.handler, + database: None, + external_context: self.external_context, + env: self.env, + // Handler that will be used by EVM. It contains handle registers + handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), phantom: PhantomData, } } } -impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, HandlerStage, EvmWiringT> +impl<'a, EvmWiringT> EvmBuilder<'a, SetGenericStage, EvmWiringT> where EvmWiringT: EvmWiring>>, { - /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. - pub fn reset_handler_with_empty_db(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { - EvmBuilder { - context: Context::new( - self.context.evm.with_db(EmptyDB::default()), - self.context.external, - ), - handler: EvmWiringT::handler::<'a>(self.handler.spec_id()), - phantom: PhantomData, - } + /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. + pub fn with_default_db(mut self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> + where + EvmWiringT::Database: Default, + { + self.database = Some(EvmWiringT::Database::default()); + self } - /// Sets the [`Database`] that will be used by [`Evm`] - /// and resets the [`Handler`] to default mainnet. - pub fn reset_handler_with_db( - self, - db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, ODB> { - EvmBuilder { - context: Context::new(self.context.evm.with_db(db), self.context.external), - handler: EvmWiringT::handler::<'a, EXT, ODB>(self.handler.spec_id()), - phantom: PhantomData, - } + pub fn with_default_ext_ctx(mut self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> + where + EvmWiringT::ExternalContext: Default, + { + self.external_context = Some(EvmWiringT::ExternalContext::default()); + self } - /// Resets [`Handler`] and sets the [`DatabaseRef`] that will be used by [`Evm`] - /// and resets the [`Handler`] to default mainnet. - pub fn reset_handler_with_ref_db( - self, - db: ODB, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { - EvmBuilder { - context: Context::new( - self.context.evm.with_db(WrapDatabaseRef(db)), - self.context.external, - ), - handler: EvmWiringT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), - phantom: PhantomData, - } + /// Sets the [`Database`] that will be used by [`Evm`]. + pub fn with_db( + mut self, + db: EvmWiringT::Database, + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { + self.database = Some(db); + self } - /// Resets [`Handler`] and sets new `ExternalContext` type. - /// and resets the [`Handler`] to default mainnet. - pub fn reset_handler_with_external_context( - self, - external: OEXT, - ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, OEXT, DB> { - EvmBuilder { - context: Context::new(self.context.evm, external), - handler: EvmWiringT::handler::<'a, OEXT, DB>(self.handler.spec_id()), - phantom: PhantomData, - } + /// Sets the external context that will be used by [`Evm`]. + pub fn with_external_context( + mut self, + external_context: EvmWiringT::ExternalContext, + ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { + self.external_context = Some(external_context); + self } + + // /// Sets Builder with [`EnvWithEvmWiring`]. + // pub fn with_env_with_handler_cfg( + // mut self, + // env_with_handler_cfg: EnvWithEvmWiring, + // ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { + // let EnvWithEvmWiring { env, spec_id } = env_with_handler_cfg; + // self.context.evm.env = env; + // EvmBuilder { + // context: self.context, + // handler: EvmWiringT::handler::<'a, EXT, DB>(spec_id), + // phantom: PhantomData, + // } + // } + + // /// Sets Builder with [`ContextWithEvmWiring`]. + // pub fn with_context_with_handler_cfg( + // self, + // context_with_handler_cfg: ContextWithEvmWiring, + // ) -> EvmBuilder<'a, HandlerStage, EvmWiringT, OEXT, ODB> { + // EvmBuilder { + // context: context_with_handler_cfg.context, + // handler: EvmWiringT::handler::<'a, OEXT, ODB>(context_with_handler_cfg.spec_id), + // phantom: PhantomData, + // } + // } + + // /// Sets Builder with [`CfgEnvWithEvmWiring`]. + // pub fn with_cfg_env_with_handler_cfg( + // mut self, + // cfg_env_and_spec_id: CfgEnvWithEvmWiring, + // ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { + // self.context.evm.env.cfg = cfg_env_and_spec_id.cfg_env; + + // EvmBuilder { + // context: self.context, + // handler: EvmWiringT::handler::<'a>(cfg_env_and_spec_id.spec_id), + // phantom: PhantomData, + // } + // } +} + +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, HandlerStage, EvmWiringT> { + // /// Creates new builder from Evm, Evm is consumed and all field are moved to Builder. + // /// It will preserve set handler and context. + // /// + // /// Builder is in HandlerStage and both database and external are set. + // pub fn new(evm: Evm<'a, EvmWiringT>) -> Self { + // Self { + // context: evm.context, + // handler: evm.handler, + // phantom: PhantomData, + // } + // } + // } + + // impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, HandlerStage, EvmWiringT> + // where + // EvmWiringT: + // EvmWiring>>, + // { + // /// Sets the [`EmptyDB`] and resets the [`Handler`] to default mainnet. + // pub fn reset_handler_with_empty_db(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { + // EvmBuilder { + // context: Context::new( + // self.context.evm.with_db(EmptyDB::default()), + // self.context.external, + // ), + // handler: EvmWiringT::handler::<'a>(self.handler.spec_id()), + // phantom: PhantomData, + // } + // } + + // /// Sets the [`Database`] that will be used by [`Evm`] + // /// and resets the [`Handler`] to default mainnet. + // pub fn reset_handler_with_db( + // self, + // db: ODB, + // ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, ODB> { + // EvmBuilder { + // context: Context::new(self.context.evm.with_db(db), self.context.external), + // handler: EvmWiringT::handler::<'a, EXT, ODB>(self.handler.spec_id()), + // phantom: PhantomData, + // } + // } + + // /// Resets [`Handler`] and sets the [`DatabaseRef`] that will be used by [`Evm`] + // /// and resets the [`Handler`] to default mainnet. + // pub fn reset_handler_with_ref_db( + // self, + // db: ODB, + // ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, EXT, WrapDatabaseRef> { + // EvmBuilder { + // context: Context::new( + // self.context.evm.with_db(WrapDatabaseRef(db)), + // self.context.external, + // ), + // handler: EvmWiringT::handler::<'a, EXT, WrapDatabaseRef>(self.handler.spec_id()), + // phantom: PhantomData, + // } + // } + + // /// Resets [`Handler`] and sets new `ExternalContext` type. + // /// and resets the [`Handler`] to default mainnet. + // pub fn reset_handler_with_external_context( + // self, + // external: OEXT, + // ) -> EvmBuilder<'a, SetGenericStage, EvmWiringT, OEXT, DB> { + // EvmBuilder { + // context: Context::new(self.context.evm, external), + // handler: EvmWiringT::handler::<'a, OEXT, DB>(self.handler.spec_id()), + // phantom: PhantomData, + // } + // } } impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWiringT> { @@ -244,19 +291,22 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi /// let evm = builder.build(); /// ``` pub fn with_handler( - self, + mut self, handler: Handler<'a, EvmWiringT, Context>, ) -> EvmBuilder<'a, BuilderStage, EvmWiringT> { - EvmBuilder { - context: self.context, - handler, - phantom: PhantomData, - } + self.handler = handler; + self } /// Builds the [`Evm`]. pub fn build(self) -> Evm<'a, EvmWiringT> { - Evm::new(self.context, self.handler) + Evm::new( + Context::new( + EvmContext::new_with_env(self.database.unwrap(), self.env.unwrap()), + self.external_context.unwrap(), + ), + self.handler, + ) } /// Register Handler that modifies the behavior of EVM. @@ -266,15 +316,10 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi pub fn append_handler_register( mut self, handle_register: register::HandleRegister, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { + ) -> EvmBuilder<'a, BuilderStage, EvmWiringT> { self.handler .append_handler_register(register::HandleRegisters::Plain(handle_register)); - EvmBuilder { - context: self.context, - handler: self.handler, - - phantom: PhantomData, - } + self } /// Register Handler that modifies the behavior of EVM. @@ -284,20 +329,15 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi pub fn append_handler_register_box( mut self, handle_register: register::HandleRegisterBox<'a, EvmWiringT>, - ) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { + ) -> EvmBuilder<'a, BuilderStage, EvmWiringT> { self.handler .append_handler_register(register::HandleRegisters::Box(handle_register)); - EvmBuilder { - context: self.context, - handler: self.handler, - - phantom: PhantomData, - } + self } /// Allows modification of Evm Database. pub fn modify_db(mut self, f: impl FnOnce(&mut EvmWiringT::Database)) -> Self { - f(&mut self.context.evm.db); + f(&mut self.database.as_mut().unwrap()); self } @@ -306,49 +346,49 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi mut self, f: impl FnOnce(&mut EvmWiringT::ExternalContext), ) -> Self { - f(&mut self.context.external); + f(&mut self.external_context.as_mut().unwrap()); self } /// Allows modification of Evm Environment. - pub fn modify_env(mut self, f: impl FnOnce(&mut Box>)) -> Self { - f(&mut self.context.evm.env); + pub fn modify_env(mut self, f: impl FnOnce(&mut Box>)) -> Self { + f(&mut self.env.as_mut().unwrap()); self } /// Sets Evm Environment. - pub fn with_env(mut self, env: Box>) -> Self { - self.context.evm.env = env; + pub fn with_env(mut self, env: Box>) -> Self { + self.env = Some(env); self } /// Allows modification of Evm's Transaction Environment. pub fn modify_tx_env(mut self, f: impl FnOnce(&mut EvmWiringT::Transaction)) -> Self { - f(&mut self.context.evm.env.tx); + f(&mut self.env.as_mut().unwrap().tx); self } /// Sets Evm's Transaction Environment. pub fn with_tx_env(mut self, tx_env: EvmWiringT::Transaction) -> Self { - self.context.evm.env.tx = tx_env; + self.env.as_mut().unwrap().tx = tx_env; self } /// Allows modification of Evm's Block Environment. pub fn modify_block_env(mut self, f: impl FnOnce(&mut EvmWiringT::Block)) -> Self { - f(&mut self.context.evm.env.block); + f(&mut self.env.as_mut().unwrap().block); self } /// Sets Evm's Block Environment. pub fn with_block_env(mut self, block_env: EvmWiringT::Block) -> Self { - self.context.evm.env.block = block_env; + self.env.as_mut().unwrap().block = block_env; self } /// Allows modification of Evm's Config Environment. pub fn modify_cfg_env(mut self, f: impl FnOnce(&mut CfgEnv)) -> Self { - f(&mut self.context.evm.env.cfg); + f(&mut self.env.as_mut().unwrap().cfg); self } } @@ -359,7 +399,7 @@ where { /// Clears Block environment of EVM. pub fn with_clear_block_env(mut self) -> Self { - self.context.evm.env.block = EvmWiringT::Block::default(); + self.env.as_mut().unwrap().block = EvmWiringT::Block::default(); self } } @@ -370,7 +410,7 @@ where { /// Clears Transaction environment of EVM. pub fn with_clear_tx_env(mut self) -> Self { - self.context.evm.env.tx = EvmWiringT::Transaction::default(); + self.env.as_mut().unwrap().tx = EvmWiringT::Transaction::default(); self } } @@ -381,7 +421,7 @@ where { /// Clears Environment of EVM. pub fn with_clear_env(mut self) -> Self { - self.context.evm.env.clear(); + self.env.as_mut().unwrap().clear(); self } } @@ -400,12 +440,7 @@ where /// expensive operation depending on registers. pub fn with_spec_id(mut self, spec_id: EvmWiringT::Hardfork) -> Self { self.handler.modify_spec_id(spec_id); - EvmBuilder { - context: self.context, - handler: self.handler, - - phantom: PhantomData, - } + self } /// Resets [`Handler`] to default mainnet. @@ -422,10 +457,12 @@ mod test { inspector::inspector_handle_register, inspectors::NoOpInspector, primitives::{ - address, AccountInfo, Address, Bytecode, Bytes, PrecompileResult, SpecId, TxKind, U256, + address, AccountInfo, Address, Bytecode, Bytes, EthereumWiring, PrecompileResult, + SpecId, TxKind, U256, }, Context, ContextPrecompile, ContextStatefulPrecompile, Evm, InMemoryDB, InnerEvmContext, }; + use alloy_provider::network::Ethereum; use revm_interpreter::{gas, Host, Interpreter}; use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; @@ -449,9 +486,8 @@ mod test { assert_eq!(*custom_context.inner.borrow(), 0); let to_capture = custom_context.clone(); - let mut evm = Evm::builder() - .with_chain_spec::() - .with_db(InMemoryDB::default()) + let mut evm = Evm::>::builder() + .with_default_db() .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) @@ -466,13 +502,12 @@ mod test { let custom_context = to_capture.clone(); // we need to use a box to capture the custom context in the instruction - let custom_instruction = Box::new( - move |_interp: &mut Interpreter, _host: &mut Context| { + let custom_instruction = + Box::new(move |_interp: &mut Interpreter, _host: &mut Context<_>| { // modify the value let mut inner = custom_context.inner.borrow_mut(); *inner += 1; - }, - ); + }); // need to ensure the instruction table is a boxed instruction table so that we // can insert the custom instruction as a boxed instruction @@ -488,163 +523,163 @@ mod test { assert_eq!(*custom_context.inner.borrow(), 1); } - #[test] - fn simple_add_instruction() { - const CUSTOM_INSTRUCTION_COST: u64 = 133; - const INITIAL_TX_GAS: u64 = 21000; - const EXPECTED_RESULT_GAS: u64 = INITIAL_TX_GAS + CUSTOM_INSTRUCTION_COST; - - fn custom_instruction(interp: &mut Interpreter, _host: &mut impl Host) { - // just spend some gas - gas!(interp, CUSTOM_INSTRUCTION_COST); - } - - let code = Bytecode::new_raw([0xED, 0x00].into()); - let code_hash = code.hash_slow(); - let to_addr = address!("ffffffffffffffffffffffffffffffffffffffff"); - - let mut evm = Evm::builder() - .with_chain_spec::() - .with_db(InMemoryDB::default()) - .modify_db(|db| { - db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) - }) - .modify_tx_env(|tx| { - let transact_to = &mut tx.transact_to; - - *transact_to = TxKind::Call(to_addr) - }) - .append_handler_register(|handler| { - handler.instruction_table.insert(0xED, custom_instruction) - }) - .build(); - - let result_and_state = evm.transact().unwrap(); - assert_eq!(result_and_state.result.gas_used(), EXPECTED_RESULT_GAS); - } - - #[test] - fn simple_build() { - // build without external with latest spec - Evm::builder().with_chain_spec::().build(); - // build with empty db - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .build(); - // build with_db - Evm::builder() - .with_chain_spec::() - .with_db(EmptyDB::default()) - .build(); - // build with empty external - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .build(); - // build with some external - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .with_external_context(()) - .build(); - // build with spec - Evm::builder() - .with_empty_db() - .with_spec_id(SpecId::HOMESTEAD) - .build(); - - // with with Env change in multiple places - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .modify_tx_env(|tx| tx.gas_limit = 10) - .build(); - Evm::builder() - .with_chain_spec::() - .modify_tx_env(|tx| tx.gas_limit = 10) - .build(); - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .modify_tx_env(|tx| tx.gas_limit = 10) - .build(); - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .modify_tx_env(|tx| tx.gas_limit = 10) - .build(); - - // with inspector handle - Evm::builder() - .with_chain_spec::() - .with_empty_db() - .with_external_context(NoOpInspector) - .append_handler_register(inspector_handle_register) - .build(); - - // create the builder - let evm = Evm::builder() - .with_db(EmptyDB::default()) - .with_chain_spec::() - .with_external_context(NoOpInspector) - .append_handler_register(inspector_handle_register) - // this would not compile - // .with_db(..) - .build(); - - let Context { external: _, .. } = evm.into_context(); - } - - #[test] - fn build_modify_build() { - // build evm - let evm = Evm::builder() - .with_empty_db() - .with_spec_id(SpecId::HOMESTEAD) - .build(); - - // modify evm - let evm = evm.modify().with_spec_id(SpecId::FRONTIER).build(); - let _ = evm - .modify() - .modify_tx_env(|tx| tx.chain_id = Some(2)) - .build(); - } - - #[test] - fn build_custom_precompile() { - struct CustomPrecompile; - - impl ContextStatefulPrecompile for CustomPrecompile { - fn call( - &self, - _input: &Bytes, - _gas_limit: u64, - _context: &mut InnerEvmContext, - ) -> PrecompileResult { - Ok(PrecompileOutput::new(10, Bytes::new())) - } - } - - let spec_id = crate::primitives::SpecId::HOMESTEAD; - - let mut evm = Evm::builder() - .with_chain_spec::() - .with_spec_id(spec_id) - .append_handler_register(|handler| { - let precompiles = handler.pre_execution.load_precompiles(); - handler.pre_execution.load_precompiles = Arc::new(move || { - let mut precompiles = precompiles.clone(); - precompiles.extend([( - Address::ZERO, - ContextPrecompile::ContextStateful(Arc::new(CustomPrecompile)), - )]); - precompiles - }); - }) - .build(); - - evm.transact().unwrap(); - } + // #[test] + // fn simple_add_instruction() { + // const CUSTOM_INSTRUCTION_COST: u64 = 133; + // const INITIAL_TX_GAS: u64 = 21000; + // const EXPECTED_RESULT_GAS: u64 = INITIAL_TX_GAS + CUSTOM_INSTRUCTION_COST; + + // fn custom_instruction(interp: &mut Interpreter, _host: &mut impl Host) { + // // just spend some gas + // gas!(interp, CUSTOM_INSTRUCTION_COST); + // } + + // let code = Bytecode::new_raw([0xED, 0x00].into()); + // let code_hash = code.hash_slow(); + // let to_addr = address!("ffffffffffffffffffffffffffffffffffffffff"); + + // let mut evm = Evm::builder() + // .with_wiring::>() + // .with_db(InMemoryDB::default()) + // .modify_db(|db| { + // db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) + // }) + // .modify_tx_env(|tx| { + // let transact_to = &mut tx.transact_to; + + // *transact_to = TxKind::Call(to_addr) + // }) + // .append_handler_register(|handler| { + // handler.instruction_table.insert(0xED, custom_instruction) + // }) + // .build(); + + // let result_and_state = evm.transact().unwrap(); + // assert_eq!(result_and_state.result.gas_used(), EXPECTED_RESULT_GAS); + // } + + // #[test] + // fn simple_build() { + // // build without external with latest spec + // Evm::builder().with_chain_spec::().build(); + // // build with empty db + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .build(); + // // build with_db + // Evm::builder() + // .with_chain_spec::() + // .with_db(EmptyDB::default()) + // .build(); + // // build with empty external + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .build(); + // // build with some external + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .with_external_context(()) + // .build(); + // // build with spec + // Evm::builder() + // .with_empty_db() + // .with_spec_id(SpecId::HOMESTEAD) + // .build(); + + // // with with Env change in multiple places + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .modify_tx_env(|tx| tx.gas_limit = 10) + // .build(); + // Evm::builder() + // .with_chain_spec::() + // .modify_tx_env(|tx| tx.gas_limit = 10) + // .build(); + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .modify_tx_env(|tx| tx.gas_limit = 10) + // .build(); + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .modify_tx_env(|tx| tx.gas_limit = 10) + // .build(); + + // // with inspector handle + // Evm::builder() + // .with_chain_spec::() + // .with_empty_db() + // .with_external_context(NoOpInspector) + // .append_handler_register(inspector_handle_register) + // .build(); + + // // create the builder + // let evm = Evm::builder() + // .with_db(EmptyDB::default()) + // .with_chain_spec::() + // .with_external_context(NoOpInspector) + // .append_handler_register(inspector_handle_register) + // // this would not compile + // // .with_db(..) + // .build(); + + // let Context { external: _, .. } = evm.into_context(); + // } + + // #[test] + // fn build_modify_build() { + // // build evm + // let evm = Evm::builder() + // .with_empty_db() + // .with_spec_id(SpecId::HOMESTEAD) + // .build(); + + // // modify evm + // let evm = evm.modify().with_spec_id(SpecId::FRONTIER).build(); + // let _ = evm + // .modify() + // .modify_tx_env(|tx| tx.chain_id = Some(2)) + // .build(); + // } + + // #[test] + // fn build_custom_precompile() { + // struct CustomPrecompile; + + // impl ContextStatefulPrecompile for CustomPrecompile { + // fn call( + // &self, + // _input: &Bytes, + // _gas_limit: u64, + // _context: &mut InnerEvmContext, + // ) -> PrecompileResult { + // Ok(PrecompileOutput::new(10, Bytes::new())) + // } + // } + + // let spec_id = crate::primitives::SpecId::HOMESTEAD; + + // let mut evm = Evm::builder() + // .with_chain_spec::() + // .with_spec_id(spec_id) + // .append_handler_register(|handler| { + // let precompiles = handler.pre_execution.load_precompiles(); + // handler.pre_execution.load_precompiles = Arc::new(move || { + // let mut precompiles = precompiles.clone(); + // precompiles.extend([( + // Address::ZERO, + // ContextPrecompile::ContextStateful(Arc::new(CustomPrecompile)), + // )]); + // precompiles + // }); + // }) + // .build(); + + // evm.transact().unwrap(); + // } } diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index 5d0f62bac6..437dc71f40 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -4,6 +4,7 @@ use crate::{ primitives::{db::Database, spec_to_generic, EthereumWiring, EvmWiring as PrimitiveEvmWiring}, EvmHandler, }; +use std::fmt::Debug; use std::vec::Vec; pub trait EvmWiring: PrimitiveEvmWiring { @@ -11,7 +12,7 @@ pub trait EvmWiring: PrimitiveEvmWiring { fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self>; } -impl EvmWiring for EthereumWiring { +impl EvmWiring for EthereumWiring { fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self> where DB: Database, diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 574615aa61..9dba878629 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -15,7 +15,7 @@ use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, primitives::{ - Address, Block as _, Bytes, Env, EthereumWiring, Log, B256, BLOCK_HASH_HISTORY, U256, + Address, Block as _, Bytes, EnvWiring, EthereumWiring, Log, B256, BLOCK_HASH_HISTORY, U256, }, EvmWiring, }; @@ -84,11 +84,11 @@ impl Host for Context { /// Returns reference to Environment. #[inline] - fn env(&self) -> &Env { + fn env(&self) -> &EnvWiring { &self.evm.env } - fn env_mut(&mut self) -> &mut Env { + fn env_mut(&mut self) -> &mut EnvWiring { &mut self.evm.env } diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 779ff389f8..5b249b5875 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -10,7 +10,8 @@ use crate::{ EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, primitives::{ - keccak256, Address, Bytecode, Bytes, CreateScheme, EVMError, EVMResultGeneric, Env, Eof, + keccak256, Address, Bytecode, Bytes, CreateScheme, EVMError, EVMResultGeneric, EnvWiring, + Eof, SpecId::{self, *}, Transaction, B256, EOF_MAGIC_BYTES, }, @@ -61,7 +62,7 @@ where { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: EvmWiringT::Database, env: Box>) -> Self { + pub fn new_with_env(db: EvmWiringT::Database, env: Box>) -> Self { Self { inner: InnerEvmContext::new_with_env(db, env), precompiles: ContextPrecompiles::default(), @@ -480,7 +481,7 @@ pub(crate) mod test_utils { pub fn create_cache_db_evm_context_with_balance< EvmWiringT: EvmWiring>, >( - env: Box>, + env: Box>, mut db: CacheDB, balance: U256, ) -> EvmContext { @@ -498,7 +499,7 @@ pub(crate) mod test_utils { /// Creates a cached db evm context. pub fn create_cache_db_evm_context>>( - env: Box>, + env: Box>, db: CacheDB, ) -> EvmContext { EvmContext { @@ -515,7 +516,7 @@ pub(crate) mod test_utils { /// Returns a new `EvmContext` with an empty journaled state. pub fn create_empty_evm_context>( - env: Box>, + env: Box>, db: EmptyDB, ) -> EvmContext { EvmContext { @@ -547,9 +548,10 @@ mod tests { // call stack is too deep. #[test] fn test_make_call_frame_stack_too_deep() { - let env = Env::::default(); + let env = EnvWiring::::default(); let db = EmptyDB::default(); - let mut context = test_utils::create_empty_evm_context(Box::new(env), db); + let mut context = + test_utils::create_empty_evm_context::(Box::new(env), db); context.journaled_state.depth = CALL_STACK_LIMIT as usize + 1; let contract = address!("dead10000000000000000000000000000001dead"); let call_inputs = test_utils::create_mock_call_inputs(contract); @@ -568,9 +570,10 @@ mod tests { // checkpointed on the journaled state correctly. #[test] fn test_make_call_frame_transfer_revert() { - let env = Env::::default(); + let env = EnvWiring::::default(); let db = EmptyDB::default(); - let mut evm_context = test_utils::create_empty_evm_context(Box::new(env), db); + let mut evm_context = + test_utils::create_empty_evm_context::(Box::new(env), db); let contract = address!("dead10000000000000000000000000000001dead"); let mut call_inputs = test_utils::create_mock_call_inputs(contract); call_inputs.value = CallValue::Transfer(U256::from(1)); @@ -589,10 +592,12 @@ mod tests { #[test] fn test_make_call_frame_missing_code_context() { - let env = Env::>::default(); + type CacheEthWiring = EthereumWiring, ()>; + let env = EnvWiring::::default(); let cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); - let mut context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); + let mut context = + create_cache_db_evm_context_with_balance::(Box::new(env), cdb, bal); let contract = address!("dead10000000000000000000000000000001dead"); let call_inputs = test_utils::create_mock_call_inputs(contract); let res = context.make_call_frame(&call_inputs); @@ -604,7 +609,8 @@ mod tests { #[test] fn test_make_call_frame_succeeds() { - let env = Env::>::default(); + type CacheEthWiring = EthereumWiring, ()>; + let env = EnvWiring::::default(); let mut cdb = CacheDB::new(EmptyDB::default()); let bal = U256::from(3_000_000_000_u128); let by = Bytecode::new_raw(Bytes::from(vec![0x60, 0x00, 0x60, 0x00])); @@ -618,7 +624,8 @@ mod tests { code: Some(by), }, ); - let mut evm_context = create_cache_db_evm_context_with_balance(Box::new(env), cdb, bal); + let mut evm_context = + create_cache_db_evm_context_with_balance::(Box::new(env), cdb, bal); let call_inputs = test_utils::create_mock_call_inputs(contract); let res = evm_context.make_call_frame(&call_inputs); let Ok(FrameOrResult::Frame(Frame::Call(call_frame))) = res else { diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index a702a4d878..4f54935f97 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -8,7 +8,7 @@ use crate::{ }, journaled_state::JournaledState, primitives::{ - AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, Env, Eof, + AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CfgEnv, EnvWiring, Eof, EvmWiring, HashSet, Spec, SpecId::{self, *}, Transaction, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, @@ -22,7 +22,7 @@ use std::{boxed::Box, sync::Arc, vec::Vec}; pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. - pub env: Box>, + pub env: Box>, /// EVM State with journaling support. pub journaled_state: JournaledState, /// Database to load data from. @@ -51,7 +51,7 @@ where impl InnerEvmContext { /// Creates a new context with the given environment and database. #[inline] - pub fn new_with_env(db: EvmWiringT::Database, env: Box>) -> Self { + pub fn new_with_env(db: EvmWiringT::Database, env: Box>) -> Self { Self { env, journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), @@ -72,7 +72,7 @@ impl InnerEvmContext { db: OWiring::Database, ) -> InnerEvmContext { InnerEvmContext { - env: Box::new(self.env.into_evm_wiring::()), + env: self.env, journaled_state: self.journaled_state, db, error: Ok(()), @@ -107,7 +107,7 @@ impl InnerEvmContext { /// Return environment. #[inline] - pub fn env(&mut self) -> &mut Env { + pub fn env(&mut self) -> &mut EnvWiring { &mut self.env } diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index 16e61296ae..5ec08ede12 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -11,9 +11,9 @@ pub mod in_memory_db; pub mod states; pub use crate::primitives::db::*; +pub use crate::primitives::db::{EmptyDB, EmptyDBTyped}; #[cfg(feature = "alloydb")] pub use alloydb::AlloyDB; -pub use crate::primitives::db::{EmptyDB, EmptyDBTyped}; #[cfg(feature = "ethersdb")] pub use ethersdb::EthersDB; pub use in_memory_db::*; diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 4a037fb7fe..0258544c42 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -1,15 +1,16 @@ use revm_interpreter::Host as _; use crate::{ - builder::{EvmBuilder, HandlerStage, SetGenericStage}, - db::{Database, DatabaseCommit, EmptyDB}, + builder::{EvmBuilder, SetGenericStage}, + db::{Database, DatabaseCommit}, handler::{EnvWithEvmWiring, Handler}, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, EVMError, EVMResult, EVMResultGeneric, EthereumWiring, ExecutionResult, - ResultAndState, SpecId, Transaction, TxKind, EOF_MAGIC_BYTES, + CfgEnv, EVMError, EVMResult, EVMResultGeneric, ExecutionResult, ResultAndState, SpecId, + Transaction, TxKind, EOF_MAGIC_BYTES, }, - Context, ContextWithEvmWiring, EvmWiring, Frame, FrameOrResult, FrameResult, + Context, ContextWithEvmWiring, EvmContext, EvmWiring, Frame, FrameOrResult, FrameResult, + InnerEvmContext, }; use core::fmt::{self, Debug}; use std::{boxed::Box, vec::Vec}; @@ -42,7 +43,9 @@ where impl> Evm<'_, EvmWiringT> { /// Commit the changes to the database. - pub fn transact_commit(&mut self) -> EVMResultGeneric, EvmWiringT> { + pub fn transact_commit( + &mut self, + ) -> EVMResultGeneric, EvmWiringT> { let ResultAndState { result, state } = self.transact()?; self.context.evm.db.commit(state); Ok(result) @@ -52,7 +55,7 @@ impl> Evm<'_, EvmWiringT> { impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> { /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. pub fn builder() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { - EvmBuilder::new_wiring() + EvmBuilder::new() } } @@ -71,8 +74,24 @@ impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> { /// Allow for evm setting to be modified by feeding current evm /// into the builder for modifications. - pub fn modify(self) -> EvmBuilder<'a, HandlerStage, EvmWiringT> { - EvmBuilder::new(self) + pub fn modify(self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { + let Evm { + context: + Context { + evm: + EvmContext { + inner: InnerEvmContext { db, env, .. }, + .. + }, + external, + }, + handler, + } = self; + // let handler = self.handler; + // let db = self.context.evm.db; + // let ext = self.context.external; + // let env = self.context.evm.env; + EvmBuilder::<'a>::new_with(db, external, env, handler) } /// Runs main call loop. diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs index fc1ea52c56..bcd4040917 100644 --- a/crates/revm/src/handler/cfg.rs +++ b/crates/revm/src/handler/cfg.rs @@ -1,12 +1,10 @@ +use crate::primitives::{CfgEnv, Env, EnvWiring, EvmWiring}; use core::{ fmt::Debug, ops::{Deref, DerefMut}, }; -use std::boxed::Box; - use derive_where::derive_where; - -use crate::primitives::{CfgEnv, Env, EvmWiring}; +use std::boxed::Box; /// Configuration environment with the chain spec id. #[derive(Debug, Eq, PartialEq)] @@ -46,7 +44,7 @@ where EvmWiringT: EvmWiring, { /// Evm enironment. - pub env: Box>, + pub env: Box>, /// Handler configuration fields. pub spec_id: EvmWiringT::Hardfork, } @@ -56,7 +54,7 @@ where EvmWiringT: EvmWiring, { /// Returns new `EnvWithHandlerCfg` instance. - pub fn new(env: Box>, spec_id: EvmWiringT::Hardfork) -> Self { + pub fn new(env: Box>, spec_id: EvmWiringT::Hardfork) -> Self { Self { env, spec_id } } @@ -88,7 +86,7 @@ impl Deref for EnvWithEvmWiring where EvmWiringT: EvmWiring, { - type Target = Env; + type Target = EnvWiring; fn deref(&self) -> &Self::Target { &self.env diff --git a/crates/revm/src/handler/handle_types/post_execution.rs b/crates/revm/src/handler/handle_types/post_execution.rs index 59bc29da0a..a799fdaa44 100644 --- a/crates/revm/src/handler/handle_types/post_execution.rs +++ b/crates/revm/src/handler/handle_types/post_execution.rs @@ -2,7 +2,7 @@ use crate::{ handler::mainnet, interpreter::Gas, - primitives::{EVMResultGeneric, ResultAndState, Spec}, + primitives::{EVMResult, EVMResultGeneric, ResultAndState, Spec}, Context, EvmWiring, FrameResult, }; use std::sync::Arc; @@ -15,25 +15,15 @@ pub type ReimburseCallerHandle<'a, EvmWiringT> = pub type RewardBeneficiaryHandle<'a, EvmWiringT> = ReimburseCallerHandle<'a, EvmWiringT>; /// Main return handle, takes state from journal and transforms internal result to external. -pub type OutputHandle<'a, EvmWiringT> = Arc< - dyn Fn( - &mut Context, - FrameResult, - ) -> EVMResultGeneric, EvmWiringT> - + 'a, ->; +pub type OutputHandle<'a, EvmWiringT> = + Arc, FrameResult) -> EVMResult + 'a>; /// End handle, takes result and state and returns final result. /// This will be called after all the other handlers. /// /// It is useful for catching errors and returning them in a different way. -pub type EndHandle<'a, EvmWiringT> = Arc< - dyn Fn( - &mut Context, - EVMResultGeneric, EvmWiringT>, - ) -> EVMResultGeneric, EvmWiringT> - + 'a, ->; +pub type EndHandle<'a, EvmWiringT> = + Arc, EVMResult) -> EVMResult + 'a>; /// Clear handle, doesn't have output, its purpose is to clear the /// context. It will always be called even on failed validation. @@ -92,7 +82,7 @@ impl<'a, EvmWiringT: EvmWiring> PostExecutionHandler<'a, EvmWiringT> { &self, context: &mut Context, result: FrameResult, - ) -> EVMResultGeneric, EvmWiringT> { + ) -> EVMResult { (self.output)(context, result) } @@ -100,8 +90,8 @@ impl<'a, EvmWiringT: EvmWiring> PostExecutionHandler<'a, EvmWiringT> { pub fn end( &self, context: &mut Context, - end_output: EVMResultGeneric, EvmWiringT>, - ) -> EVMResultGeneric, EvmWiringT> { + end_output: EVMResultGeneric, EvmWiringT>, + ) -> EVMResult { (self.end)(context, end_output) } diff --git a/crates/revm/src/handler/handle_types/validation.rs b/crates/revm/src/handler/handle_types/validation.rs index 8884226283..c5f7309622 100644 --- a/crates/revm/src/handler/handle_types/validation.rs +++ b/crates/revm/src/handler/handle_types/validation.rs @@ -1,13 +1,13 @@ use crate::{ handler::mainnet, - primitives::{EVMResultGeneric, Env, InvalidTransaction, Spec, TransactionValidation}, + primitives::{EVMResultGeneric, EnvWiring, InvalidTransaction, Spec, TransactionValidation}, Context, EvmWiring, }; use std::sync::Arc; /// Handle that validates env. pub type ValidateEnvHandle<'a, EvmWiringT> = - Arc) -> EVMResultGeneric<(), EvmWiringT> + 'a>; + Arc) -> EVMResultGeneric<(), EvmWiringT> + 'a>; /// Handle that validates transaction environment against the state. /// Second parametar is initial gas. @@ -16,7 +16,7 @@ pub type ValidateTxEnvAgainstState<'a, EvmWiringT> = /// Initial gas calculation handle pub type ValidateInitialTxGasHandle<'a, EvmWiringT> = - Arc) -> EVMResultGeneric + 'a>; + Arc) -> EVMResultGeneric + 'a>; /// Handles related to validation. pub struct ValidationHandler<'a, EvmWiringT: EvmWiring> { @@ -44,12 +44,12 @@ where impl<'a, EvmWiringT: EvmWiring> ValidationHandler<'a, EvmWiringT> { /// Validate env. - pub fn env(&self, env: &Env) -> EVMResultGeneric<(), EvmWiringT> { + pub fn env(&self, env: &EnvWiring) -> EVMResultGeneric<(), EvmWiringT> { (self.env)(env) } /// Initial gas - pub fn initial_tx_gas(&self, env: &Env) -> EVMResultGeneric { + pub fn initial_tx_gas(&self, env: &EnvWiring) -> EVMResultGeneric { (self.initial_tx_gas)(env) } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 361704bdc1..6270b9b219 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -4,7 +4,7 @@ use crate::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, SharedMemory, }, - primitives::{EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction}, + primitives::{EVMError, EVMResultGeneric, EnvWiring, Spec, SpecId, Transaction}, CallFrame, Context, CreateFrame, EvmWiring, Frame, FrameOrResult, FrameResult, }; use core::mem; @@ -37,7 +37,7 @@ pub fn execute_frame( /// Helper function called inside [`last_frame_return`] #[inline] pub fn frame_return_with_refund_flag( - env: &Env, + env: &EnvWiring, frame_result: &mut FrameResult, refund_enabled: bool, ) { @@ -217,7 +217,7 @@ mod tests { /// Creates frame result. fn call_last_frame_return(instruction_result: InstructionResult, gas: Gas) -> Gas { - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.gas_limit = 100; let mut first_frame = FrameResult::Call(CallOutcome::new( diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index 45f6f01803..17ae154a2a 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,8 +1,8 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - Block, Bytecode, EVMError, EVMResultGeneric, ExecutionResult, ResultAndState, Spec, - SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, + Block, Bytecode, EVMError, EVMResult, EVMResultGeneric, ExecutionResult, ResultAndState, + Spec, SpecId::LONDON, Transaction, KECCAK_EMPTY, U256, }, Context, EvmWiring, FrameResult, }; @@ -11,8 +11,8 @@ use crate::{ #[inline] pub fn end( _context: &mut Context, - evm_output: EVMResultGeneric, EvmWiringT>, -) -> EVMResultGeneric, EvmWiringT> { + evm_output: EVMResult, +) -> EVMResult { evm_output } @@ -89,7 +89,7 @@ pub fn reimburse_caller( pub fn output( context: &mut Context, result: FrameResult, -) -> EVMResultGeneric, EvmWiringT> { +) -> EVMResult { context.evm.take_error().map_err(EVMError::Database)?; // used gas with refund calculated. diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 959814e777..415368d443 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -5,7 +5,7 @@ use crate::{ precompile::PrecompileSpecId, primitives::{ - Account, Block, EVMError, EVMResultGeneric, Env, Spec, SpecId, Transaction, + Account, Block, EVMError, EVMResultGeneric, EnvWiring, Spec, SpecId, Transaction, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, EvmWiring, @@ -126,7 +126,7 @@ pub fn load_accounts( #[inline] pub fn deduct_caller_inner( caller_account: &mut Account, - env: &Env, + env: &EnvWiring, ) { // Subtract gas costs from the caller's account. // We need to saturate the gas cost to prevent underflow in case that `disable_balance_check` is enabled. diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index ca4879d8c2..32f24bcf2c 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -2,7 +2,7 @@ use revm_interpreter::gas; use crate::{ primitives::{ - EVMError, EVMResultGeneric, Env, InvalidTransaction, Spec, Transaction, + EVMError, EVMResultGeneric, EnvWiring, InvalidTransaction, Spec, Transaction, TransactionValidation, }, Context, EvmWiring, @@ -10,7 +10,7 @@ use crate::{ /// Validate environment for the mainnet. pub fn validate_env( - env: &Env, + env: &EnvWiring, ) -> EVMResultGeneric<(), EvmWiringT> where ::ValidationError: From, @@ -50,7 +50,7 @@ where /// Validate initial transaction gas. pub fn validate_initial_tx_gas( - env: &Env, + env: &EnvWiring, ) -> EVMResultGeneric where ::ValidationError: From, diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index ed73545b95..c7abd718fb 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -9,7 +9,7 @@ use crate::{ inspectors::GasInspector, interpreter::{CallInputs, CreateInputs, Interpreter}, primitives::{Address, U256}, - Database, EvmContext, EvmWiring, Inspector, + EvmContext, EvmWiring, Inspector, }; /// Custom print [Inspector], it has step level information of execution. @@ -120,7 +120,7 @@ mod test { use crate::{ inspector_handle_register, inspectors::CustomPrintTracer, - primitives::{address, bytes, SpecId}, + primitives::{address, bytes, EthereumWiring, SpecId}, Evm, InMemoryDB, }; @@ -130,8 +130,9 @@ mod test { // https://github.com/bluealloy/revm/issues/277 // checks this use case - let mut evm = Evm::builder() - .with_db(InMemoryDB::default()) + let mut evm = Evm::>::builder() + .with_default_db() + .with_default_ext_ctx() .modify_db(|db| { let code = bytes!("5b597fb075978b6c412c64d169d56d839a8fe01b3f4607ed603b2c78917ce8be1430fe6101e8527ffe64706ecad72a2f5c97a95e006e279dc57081902029ce96af7edae5de116fec610208527f9fc1ef09d4dd80683858ae3ea18869fe789ddc365d8d9d800e26c9872bac5e5b6102285260276102485360d461024953601661024a53600e61024b53607d61024c53600961024d53600b61024e5360b761024f5360596102505360796102515360a061025253607261025353603a6102545360fb61025553601261025653602861025753600761025853606f61025953601761025a53606161025b53606061025c5360a661025d53602b61025e53608961025f53607a61026053606461026153608c6102625360806102635360d56102645360826102655360ae61026653607f6101e8610146610220677a814b184591c555735fdcca53617f4d2b9134b29090c87d01058e27e962047654f259595947443b1b816b65cdb6277f4b59c10a36f4e7b8658f5a5e6f5561"); let info = crate::primitives::AccountInfo { @@ -148,7 +149,6 @@ mod test { tx.data = crate::primitives::Bytes::new(); tx.value = crate::primitives::U256::ZERO; }) - .with_external_context(CustomPrintTracer::default()) .with_spec_id(SpecId::BERLIN) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index b1da062f70..eeb04e5592 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -3,15 +3,18 @@ use crate::{ interpreter::{ CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterResult, }, - primitives::{db::Database, hex, HashMap, Transaction, B256, U256}, + primitives::{hex, HashMap, Transaction, B256, U256}, EvmContext, EvmWiring, Inspector, }; +use derive_where::derive_where; use revm_interpreter::OpCode; use serde::Serialize; use std::io::Write; /// [EIP-3155](https://eips.ethereum.org/EIPS/eip-3155) tracer [Inspector]. +#[derive_where(Debug)] pub struct TracerEip3155 { + #[derive_where(skip)] output: Box, gas_inspector: GasInspector, @@ -162,7 +165,7 @@ impl TracerEip3155 { self.output.flush() } - fn print_summary( + fn print_summary( &mut self, result: &InterpreterResult, context: &mut EvmContext, diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 738b34a248..587802b805 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -4,7 +4,6 @@ use revm_interpreter::CallOutcome; use crate::{ interpreter::{CallInputs, CreateInputs, CreateOutcome}, - primitives::db::Database, EvmContext, EvmWiring, Inspector, }; @@ -86,7 +85,7 @@ mod tests { use crate::{ interpreter::Interpreter, - primitives::{self, Log}, + primitives::{self, EthereumWiring, Log}, }; type TestEvmWiring = primitives::DefaultEthereumWiring; @@ -190,10 +189,9 @@ mod tests { ]); let bytecode = Bytecode::new_raw(contract_data); - let mut evm = Evm::builder() - .with_chain_spec::() + let mut evm = Evm::>::builder() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) - .with_external_context(StackInspector::default()) + .with_default_ext_ctx() .modify_tx_env(|tx| { *tx = ::Transaction::default(); diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index d597407244..147efe9949 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -1,5 +1,4 @@ use crate::{ - db::Database, handler::register::EvmHandler, interpreter::{opcode, InstructionResult, Interpreter}, primitives::EVMResultGeneric, @@ -257,7 +256,8 @@ mod tests { use crate::{ inspectors::NoOpInspector, interpreter::{CallInputs, CallOutcome, CreateInputs, CreateOutcome}, - primitives, Evm, EvmContext, + primitives::{self, db::EmptyDB, EthereumWiring}, + Evm, EvmContext, }; type TestEvmWiring = primitives::DefaultEthereumWiring; @@ -364,8 +364,8 @@ mod tests { ]); let bytecode = Bytecode::new_raw(contract_data); - let mut evm = Evm::builder() - .with_chain_spec::() + let mut evm = Evm::>::builder() + .with_default_ext_ctx() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .with_external_context(StackInspector::default()) .modify_tx_env(|tx| { @@ -393,7 +393,7 @@ mod tests { #[test] fn test_inspector_reg() { let mut noop = NoOpInspector; - let _evm = Evm::builder() + let _evm: Evm<'_, EthereumWiring> = Evm::builder() .with_external_context(&mut noop) .append_handler_register(inspector_handle_register) .build(); diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index e2971af309..8c1c4f16a0 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -55,7 +55,7 @@ pub fn optimism_handle_register( /// Validate environment for the Optimism chain. pub fn validate_env( - env: &Env, + env: &EnvWiring, ) -> Result<(), EVMError> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. if env.tx.source_hash().is_some() { From d73f96ca74e2e9213e3f1b76d21883cce403852d Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 6 Aug 2024 14:49:48 +0200 Subject: [PATCH 40/59] chore: cleanup rename --- .../primitives/src/{chain_spec.rs => evm_wiring.rs} | 12 ++---------- crates/primitives/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 12 deletions(-) rename crates/primitives/src/{chain_spec.rs => evm_wiring.rs} (81%) diff --git a/crates/primitives/src/chain_spec.rs b/crates/primitives/src/evm_wiring.rs similarity index 81% rename from crates/primitives/src/chain_spec.rs rename to crates/primitives/src/evm_wiring.rs index 17a55db64a..a22ff5510b 100644 --- a/crates/primitives/src/chain_spec.rs +++ b/crates/primitives/src/evm_wiring.rs @@ -12,20 +12,12 @@ impl HardforkTrait for HardforkT where { } -// cfg_if! { -// if #[cfg(feature = "serde")] { -// pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} - -// impl HaltReasonTrait for HaltReasonT where -// HaltReasonT: Clone + Debug + PartialEq + Eq + From + for<'a> serde::Deserialize<'a> + serde::Serialize {} -// } else { pub trait HaltReasonTrait: Clone + Debug + PartialEq + Eq + From {} + impl HaltReasonTrait for HaltReasonT where HaltReasonT: Clone + Debug + PartialEq + Eq + From { } -// } -// } pub trait TransactionValidation { cfg_if! { @@ -67,9 +59,9 @@ impl EvmWiring for EthereumWiring { type Database = DB; type ExternalContext = EXT; type Block = crate::BlockEnv; + type Transaction = crate::TxEnv; type Hardfork = SpecId; type HaltReason = crate::HaltReason; - type Transaction = crate::TxEnv; } pub type DefaultEthereumWiring = EthereumWiring; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index ae0582f45f..e0c485c775 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -12,7 +12,7 @@ pub mod db; pub mod env; mod bytecode; -mod chain_spec; +mod evm_wiring; mod constants; #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg; @@ -29,7 +29,7 @@ pub use alloy_primitives::{ }; pub use bitvec; pub use bytecode::*; -pub use chain_spec::*; +pub use evm_wiring::*; pub use constants::*; pub use env::*; From 763ba26a02521ef17fa5979b610bc15065051d18 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 6 Aug 2024 15:59:50 +0200 Subject: [PATCH 41/59] nit --- crates/primitives/src/evm_wiring.rs | 3 ++- crates/primitives/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/primitives/src/evm_wiring.rs b/crates/primitives/src/evm_wiring.rs index a22ff5510b..c987f6cdab 100644 --- a/crates/primitives/src/evm_wiring.rs +++ b/crates/primitives/src/evm_wiring.rs @@ -33,7 +33,8 @@ pub trait TransactionValidation { pub trait EvmWiring: Sized { /// External type - type ExternalContext: Sized + Debug; + type ExternalContext: Sized; + /// Database type. type Database: Database; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index e0c485c775..2434be42c7 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -12,8 +12,8 @@ pub mod db; pub mod env; mod bytecode; -mod evm_wiring; mod constants; +mod evm_wiring; #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg; pub mod precompile; @@ -29,9 +29,9 @@ pub use alloy_primitives::{ }; pub use bitvec; pub use bytecode::*; -pub use evm_wiring::*; pub use constants::*; pub use env::*; +pub use evm_wiring::*; cfg_if::cfg_if! { if #[cfg(all(not(feature = "hashbrown"), feature = "std"))] { From b96b3973a7461004edd11b380aceac5dde53e5ed Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 28 Aug 2024 18:02:53 +0000 Subject: [PATCH 42/59] fix: make string conversion complete --- crates/primitives/src/specification.rs | 104 ++++++++++++++++--------- crates/revm/src/optimism/spec.rs | 71 ++++++++++------- 2 files changed, 111 insertions(+), 64 deletions(-) diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index db141155dc..933bad621b 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -53,25 +53,55 @@ impl SpecId { } } +/// String identifiers for hardforks. +pub mod id { + pub const FRONTIER: &str = "Frontier"; + pub const FRONTIER_THAWING: &str = "Frontier Thawing"; + pub const HOMESTEAD: &str = "Homestead"; + pub const DAO_FORK: &str = "DAO Fork"; + pub const TANGERINE: &str = "Tangerine"; + pub const SPURIOUS_DRAGON: &str = "Spurious"; + pub const BYZANTIUM: &str = "Byzantium"; + pub const CONSTANTINOPLE: &str = "Constantinople"; + pub const PETERSBURG: &str = "Petersburg"; + pub const ISTANBUL: &str = "Istanbul"; + pub const MUIR_GLACIER: &str = "MuirGlacier"; + pub const BERLIN: &str = "Berlin"; + pub const LONDON: &str = "London"; + pub const ARROW_GLACIER: &str = "Arrow Glacier"; + pub const GRAY_GLACIER: &str = "Gray Glacier"; + pub const MERGE: &str = "Merge"; + pub const SHANGHAI: &str = "Shanghai"; + pub const CANCUN: &str = "Cancun"; + pub const PRAGUE: &str = "Prague"; + pub const PRAGUE_EOF: &str = "PragueEOF"; + pub const LATEST: &str = "Latest"; +} + impl From<&str> for SpecId { fn from(name: &str) -> Self { match name { - "Frontier" => Self::FRONTIER, - "Homestead" => Self::HOMESTEAD, - "Tangerine" => Self::TANGERINE, - "Spurious" => Self::SPURIOUS_DRAGON, - "Byzantium" => Self::BYZANTIUM, - "Constantinople" => Self::CONSTANTINOPLE, - "Petersburg" => Self::PETERSBURG, - "Istanbul" => Self::ISTANBUL, - "MuirGlacier" => Self::MUIR_GLACIER, - "Berlin" => Self::BERLIN, - "London" => Self::LONDON, - "Merge" => Self::MERGE, - "Shanghai" => Self::SHANGHAI, - "Cancun" => Self::CANCUN, - "Prague" => Self::PRAGUE, - "PragueEOF" => Self::PRAGUE_EOF, + id::FRONTIER => Self::FRONTIER, + id::FRONTIER_THAWING => Self::FRONTIER_THAWING, + id::HOMESTEAD => Self::HOMESTEAD, + id::DAO_FORK => Self::DAO_FORK, + id::TANGERINE => Self::TANGERINE, + id::SPURIOUS_DRAGON => Self::SPURIOUS_DRAGON, + id::BYZANTIUM => Self::BYZANTIUM, + id::CONSTANTINOPLE => Self::CONSTANTINOPLE, + id::PETERSBURG => Self::PETERSBURG, + id::ISTANBUL => Self::ISTANBUL, + id::MUIR_GLACIER => Self::MUIR_GLACIER, + id::BERLIN => Self::BERLIN, + id::LONDON => Self::LONDON, + id::ARROW_GLACIER => Self::ARROW_GLACIER, + id::GRAY_GLACIER => Self::GRAY_GLACIER, + id::MERGE => Self::MERGE, + id::SHANGHAI => Self::SHANGHAI, + id::CANCUN => Self::CANCUN, + id::PRAGUE => Self::PRAGUE, + id::PRAGUE_EOF => Self::PRAGUE_EOF, + id::LATEST => Self::LATEST, _ => Self::LATEST, } } @@ -80,27 +110,27 @@ impl From<&str> for SpecId { impl From for &'static str { fn from(spec_id: SpecId) -> Self { match spec_id { - SpecId::FRONTIER => "Frontier", - SpecId::FRONTIER_THAWING => "Frontier Thawing", - SpecId::HOMESTEAD => "Homestead", - SpecId::DAO_FORK => "DAO Fork", - SpecId::TANGERINE => "Tangerine", - SpecId::SPURIOUS_DRAGON => "Spurious", - SpecId::BYZANTIUM => "Byzantium", - SpecId::CONSTANTINOPLE => "Constantinople", - SpecId::PETERSBURG => "Petersburg", - SpecId::ISTANBUL => "Istanbul", - SpecId::MUIR_GLACIER => "MuirGlacier", - SpecId::BERLIN => "Berlin", - SpecId::LONDON => "London", - SpecId::ARROW_GLACIER => "Arrow Glacier", - SpecId::GRAY_GLACIER => "Gray Glacier", - SpecId::MERGE => "Merge", - SpecId::SHANGHAI => "Shanghai", - SpecId::CANCUN => "Cancun", - SpecId::PRAGUE => "Prague", - SpecId::PRAGUE_EOF => "PragueEOF", - SpecId::LATEST => "Latest", + SpecId::FRONTIER => id::FRONTIER, + SpecId::FRONTIER_THAWING => id::FRONTIER_THAWING, + SpecId::HOMESTEAD => id::HOMESTEAD, + SpecId::DAO_FORK => id::DAO_FORK, + SpecId::TANGERINE => id::TANGERINE, + SpecId::SPURIOUS_DRAGON => id::SPURIOUS_DRAGON, + SpecId::BYZANTIUM => id::BYZANTIUM, + SpecId::CONSTANTINOPLE => id::CONSTANTINOPLE, + SpecId::PETERSBURG => id::PETERSBURG, + SpecId::ISTANBUL => id::ISTANBUL, + SpecId::MUIR_GLACIER => id::MUIR_GLACIER, + SpecId::BERLIN => id::BERLIN, + SpecId::LONDON => id::LONDON, + SpecId::ARROW_GLACIER => id::ARROW_GLACIER, + SpecId::GRAY_GLACIER => id::GRAY_GLACIER, + SpecId::MERGE => id::MERGE, + SpecId::SHANGHAI => id::SHANGHAI, + SpecId::CANCUN => id::CANCUN, + SpecId::PRAGUE => id::PRAGUE, + SpecId::PRAGUE_EOF => id::PRAGUE_EOF, + SpecId::LATEST => id::LATEST, } } } diff --git a/crates/revm/src/optimism/spec.rs b/crates/revm/src/optimism/spec.rs index 2ee9a97354..add7fcd482 100644 --- a/crates/revm/src/optimism/spec.rs +++ b/crates/revm/src/optimism/spec.rs @@ -177,30 +177,47 @@ impl From for PrecompileSpecId { } } +/// String identifiers for Optimism hardforks. +pub mod id { + // Re-export the Ethereum hardforks. + pub use crate::primitives::specification::id::*; + + pub const BEDROCK: &str = "Bedrock"; + pub const REGOLITH: &str = "Regolith"; + pub const CANYON: &str = "Canyon"; + pub const ECOTONE: &str = "Ecotone"; + pub const FJORD: &str = "Fjord"; +} + impl From<&str> for OptimismSpecId { fn from(name: &str) -> Self { match name { - "Frontier" => Self::FRONTIER, - "Homestead" => Self::HOMESTEAD, - "Tangerine" => Self::TANGERINE, - "Spurious" => Self::SPURIOUS_DRAGON, - "Byzantium" => Self::BYZANTIUM, - "Constantinople" => Self::CONSTANTINOPLE, - "Petersburg" => Self::PETERSBURG, - "Istanbul" => Self::ISTANBUL, - "MuirGlacier" => Self::MUIR_GLACIER, - "Berlin" => Self::BERLIN, - "London" => Self::LONDON, - "Merge" => Self::MERGE, - "Shanghai" => Self::SHANGHAI, - "Cancun" => Self::CANCUN, - "Prague" => Self::PRAGUE, - "PragueEOF" => Self::PRAGUE_EOF, - "Bedrock" => Self::BEDROCK, - "Regolith" => Self::REGOLITH, - "Canyon" => Self::CANYON, - "Ecotone" => Self::ECOTONE, - "Fjord" => Self::FJORD, + id::FRONTIER => Self::FRONTIER, + id::FRONTIER_THAWING => Self::FRONTIER_THAWING, + id::HOMESTEAD => Self::HOMESTEAD, + id::DAO_FORK => Self::DAO_FORK, + id::TANGERINE => Self::TANGERINE, + id::SPURIOUS_DRAGON => Self::SPURIOUS_DRAGON, + id::BYZANTIUM => Self::BYZANTIUM, + id::CONSTANTINOPLE => Self::CONSTANTINOPLE, + id::PETERSBURG => Self::PETERSBURG, + id::ISTANBUL => Self::ISTANBUL, + id::MUIR_GLACIER => Self::MUIR_GLACIER, + id::BERLIN => Self::BERLIN, + id::LONDON => Self::LONDON, + id::ARROW_GLACIER => Self::ARROW_GLACIER, + id::GRAY_GLACIER => Self::GRAY_GLACIER, + id::MERGE => Self::MERGE, + id::SHANGHAI => Self::SHANGHAI, + id::CANCUN => Self::CANCUN, + id::PRAGUE => Self::PRAGUE, + id::PRAGUE_EOF => Self::PRAGUE_EOF, + id::BEDROCK => Self::BEDROCK, + id::REGOLITH => Self::REGOLITH, + id::CANYON => Self::CANYON, + id::ECOTONE => Self::ECOTONE, + id::FJORD => Self::FJORD, + id::LATEST => Self::LATEST, _ => Self::LATEST, } } @@ -229,12 +246,12 @@ impl From for &'static str { | OptimismSpecId::CANCUN | OptimismSpecId::PRAGUE | OptimismSpecId::PRAGUE_EOF => value.into_eth_spec_id().into(), - OptimismSpecId::BEDROCK => "Bedrock", - OptimismSpecId::REGOLITH => "Regolith", - OptimismSpecId::CANYON => "Canyon", - OptimismSpecId::ECOTONE => "Ecotone", - OptimismSpecId::FJORD => "Fjord", - OptimismSpecId::LATEST => "Latest", + OptimismSpecId::BEDROCK => id::BEDROCK, + OptimismSpecId::REGOLITH => id::REGOLITH, + OptimismSpecId::CANYON => id::CANYON, + OptimismSpecId::ECOTONE => id::ECOTONE, + OptimismSpecId::FJORD => id::FJORD, + OptimismSpecId::LATEST => id::LATEST, } } } From 65d4f263e93b0f041caf7dd01997e7ab344ab09a Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 2 Sep 2024 15:12:06 +0200 Subject: [PATCH 43/59] fix compile --- crates/interpreter/src/host.rs | 2 +- crates/primitives/src/env.rs | 2 +- crates/revm/src/builder.rs | 6 ++---- crates/revm/src/context/evm_context.rs | 6 ++++-- crates/revm/src/evm.rs | 7 +++++-- crates/revm/src/handler/handle_types/generic.rs | 14 +++----------- .../revm/src/handler/handle_types/pre_execution.rs | 10 +++++----- crates/revm/src/handler/mainnet/execution.rs | 8 ++++---- crates/revm/src/handler/mainnet/post_execution.rs | 7 ++++--- 9 files changed, 29 insertions(+), 33 deletions(-) diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 29e7b47300..377985b0d8 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -1,4 +1,4 @@ -use crate::primitives::{Address, Bytes, Env, Log, B256, U256}; +use crate::primitives::{Address, Bytes, Log, B256, U256}; use core::ops::{Deref, DerefMut}; mod dummy; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index f3615300dc..6d616e1f55 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,5 +1,5 @@ use crate::{ - calc_blob_gasprice, AccessListItem, Account, Address, AuthorizationList, Block, Bytes, EvmWiring, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, B256, GAS_PER_BLOB, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG + calc_blob_gasprice, AccessListItem, Account, Address, AuthorizationList, Block, Bytes, EvmWiring, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, B256, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG }; use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 52c9db7dc5..f69a84a070 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -1,9 +1,7 @@ use crate::{ - db::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}, + db::EmptyDB, handler::register, - primitives::{ - self, CfgEnv, Env, EnvWiring, EthereumWiring, InvalidTransaction, TransactionValidation, - }, + primitives::{CfgEnv, EnvWiring, EthereumWiring, InvalidTransaction, TransactionValidation}, Context, Evm, EvmContext, EvmWiring, Handler, }; use core::marker::PhantomData; diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 17c6b1b871..a5e645ff11 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -165,7 +165,8 @@ where let _ = self .inner .journaled_state - .load_account_delegated(inputs.bytecode_address, &mut self.inner.db)?; + .load_account_delegated(inputs.bytecode_address, &mut self.inner.db) + .map_err(EVMError::Database)?; // Create subroutine checkpoint let checkpoint = self.journaled_state.checkpoint(); @@ -235,7 +236,8 @@ where bytecode = self .inner .journaled_state - .load_code(eip7702_bytecode.delegated_address, &mut self.inner.db)? + .load_code(eip7702_bytecode.delegated_address, &mut self.inner.db) + .map_err(EVMError::Database)? .info .code .clone() diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 5ff15657cb..b5facbdb95 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -420,7 +420,10 @@ mod tests { use crate::{ db::BenchmarkDB, interpreter::opcode::{PUSH1, SSTORE}, - primitives::{address, Authorization, Bytecode, RecoveredAuthorization, Signature, U256}, + primitives::{ + address, Authorization, Bytecode, EthereumWiring, RecoveredAuthorization, Signature, + U256, + }, }; #[test] @@ -431,7 +434,7 @@ mod tests { let bytecode = Bytecode::new_legacy([PUSH1, 0x01, PUSH1, 0x01, SSTORE].into()); - let mut evm = Evm::builder() + let mut evm = Evm::>::builder() .with_spec_id(SpecId::PRAGUE) .with_db(BenchmarkDB::new_bytecode(bytecode)) .modify_tx_env(|tx| { diff --git a/crates/revm/src/handler/handle_types/generic.rs b/crates/revm/src/handler/handle_types/generic.rs index 443ac26aa1..52ec25651f 100644 --- a/crates/revm/src/handler/handle_types/generic.rs +++ b/crates/revm/src/handler/handle_types/generic.rs @@ -1,17 +1,9 @@ -use crate::{ - primitives::{db::Database, EVMResultGeneric, EvmWiring}, - Context, -}; +use crate::{primitives::EVMResultGeneric, Context}; use std::sync::Arc; /// Generic Handle that takes a mutable reference to the context and returns a result. pub type GenericContextHandle<'a, EvmWiring> = GenericContextHandleRet<'a, EvmWiring, ()>; /// Generic handle that takes a mutable reference to the context and returns a result. -pub type GenericContextHandleRet<'a, EvmWiringT, ReturnT> = Arc< - dyn Fn( - &mut Context, - ) - -> EVMResultGeneric::Database as Database>::Error> - + 'a, ->; +pub type GenericContextHandleRet<'a, EvmWiringT, ReturnT> = + Arc) -> EVMResultGeneric + 'a>; diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 2b721393ef..486f90a620 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -3,7 +3,7 @@ use super::{GenericContextHandle, GenericContextHandleRet}; use crate::{ handler::mainnet, primitives::{EVMResultGeneric, Spec}, - Context, ContextPrecompiles,EvmWiring + Context, ContextPrecompiles, EvmWiring, }; use std::sync::Arc; @@ -14,19 +14,19 @@ pub type LoadPrecompilesHandle<'a, EvmWiringT> = /// Load access list accounts and beneficiary. /// There is no need to load Caller as it is assumed that /// it will be loaded in DeductCallerHandle. -pub type LoadAccountsHandle<'a, EvmWiring> = GenericContextHandle<'a, EvmWiring>; +pub type LoadAccountsHandle<'a, EvmWiringT> = GenericContextHandle<'a, EvmWiringT>; /// Deduct the caller to its limit. -pub type DeductCallerHandle<'a, EvmWiring> = GenericContextHandle<'a, EvmWiring>; +pub type DeductCallerHandle<'a, EvmWiringT> = GenericContextHandle<'a, EvmWiringT>; /// Load Auth list for EIP-7702, and returns number of created accounts. -pub type ApplyEIP7702AuthListHandle<'a, EvmWiring> = GenericContextHandleRet<'a, EvmWiring, u64>; +pub type ApplyEIP7702AuthListHandle<'a, EvmWiringT> = GenericContextHandleRet<'a, EvmWiringT, u64>; /// Handles related to pre execution before the stack loop is started. pub struct PreExecutionHandler<'a, EvmWiringT: EvmWiring> { /// Load precompiles pub load_precompiles: LoadPrecompilesHandle<'a, EvmWiringT>, - /// Main load handle + // /// Main load handle pub load_accounts: LoadAccountsHandle<'a, EvmWiringT>, /// Deduct max value from the caller. pub deduct_caller: DeductCallerHandle<'a, EvmWiringT>, diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 869592bfa8..d7b11f1a65 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -4,7 +4,7 @@ use crate::{ return_ok, return_revert, CallInputs, CreateInputs, CreateOutcome, Gas, InstructionResult, SharedMemory, }, - primitives::{EVMError, EVMResultGeneric, Spec}, + primitives::{EVMError, EVMResultGeneric, Spec, Transaction}, CallFrame, Context, CreateFrame, EvmWiring, Frame, FrameOrResult, FrameResult, }; use core::mem; @@ -46,7 +46,7 @@ pub fn last_frame_return( let refunded = gas.refunded(); // Spend the gas limit. Gas is reimbursed when the tx returns successfully. - *gas = Gas::new_spent(context.evm.env.tx.gas_limit); + *gas = Gas::new_spent(context.evm.env.tx.gas_limit()); match instruction_result { return_ok!() => { @@ -201,7 +201,7 @@ mod tests { let mut env = EnvWiring::::default(); env.tx.gas_limit = 100; - let mut ctx = Context::new_empty(); + let mut ctx = Context::default(); ctx.evm.inner.env = Box::new(env); let mut first_frame = FrameResult::Call(CallOutcome::new( InterpreterResult { @@ -212,7 +212,7 @@ mod tests { 0..0, )); last_frame_return::(&mut ctx, &mut first_frame).unwrap(); - refund::(&mut ctx, first_frame.gas_mut(), 0); + refund::(&mut ctx, first_frame.gas_mut(), 0); *first_frame.gas() } diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index dcbae8d29a..784ab53540 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,7 +1,8 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, EVMError, ExecutionResult, ResultAndState, Spec, SpecId, SpecId::LONDON, U256, + Block, EVMError, EVMResult, EVMResultGeneric, ExecutionResult, ResultAndState, Spec, + SpecId, SpecId::LONDON, Transaction, U256, }, Context, EvmWiring, FrameResult, }; @@ -75,7 +76,7 @@ pub fn reimburse_caller( context: &mut Context, gas: &Gas, ) -> EVMResultGeneric<(), EvmWiringT> { - let caller = context.evm.env.tx.caller(); + let caller = *context.evm.env.tx.caller(); let effective_gas_price = context.evm.env.effective_gas_price(); // return balance of not spend gas. @@ -83,7 +84,7 @@ pub fn reimburse_caller( .evm .inner .journaled_state - .load_account(*caller, &mut context.evm.inner.db) + .load_account(caller, &mut context.evm.inner.db) .map_err(EVMError::Database)?; caller_account.data.info.balance = From 917a75346cca01c36b23d982c4e609aeaed8b841 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 4 Sep 2024 02:34:18 +0200 Subject: [PATCH 44/59] compiles --- Cargo.lock | 20 +- Cargo.toml | 3 +- bins/revm-test/src/bin/analysis.rs | 8 +- bins/revm-test/src/bin/burntpix/main.rs | 4 +- bins/revm-test/src/bin/snailtracer.rs | 8 +- bins/revm-test/src/bin/transfer.rs | 9 +- bins/revme/src/cmd/evmrunner.rs | 2 +- bins/revme/src/cmd/statetest/runner.rs | 4 +- crates/optimism/CHANGELOG.md | 0 crates/optimism/Cargo.toml | 91 +++++++++ crates/optimism/LICENSE | 21 +++ .../src/optimism => optimism/src}/bn128.rs | 6 +- .../src/optimism => optimism/src}/env.rs | 4 +- .../src/optimism => optimism/src}/fast_lz.rs | 21 ++- .../src}/handler_register.rs | 176 +++++++++--------- .../src/optimism => optimism/src}/l1block.rs | 6 +- .../src/optimism.rs => optimism/src/lib.rs} | 11 +- .../src/optimism => optimism/src}/result.rs | 2 +- .../src/optimism => optimism/src}/spec.rs | 145 ++++++++------- crates/primitives/src/env.rs | 5 +- crates/primitives/src/evm_wiring.rs | 6 +- crates/revm/Cargo.toml | 11 +- crates/revm/src/context.rs | 10 +- crates/revm/src/context/evm_context.rs | 4 +- crates/revm/src/context/inner_evm_context.rs | 14 +- crates/revm/src/db/in_memory_db.rs | 7 +- crates/revm/src/lib.rs | 6 - examples/db_by_ref.rs | 21 ++- examples/fork_ref_transact.rs | 3 +- examples/generate_block_traces.rs | 4 +- 30 files changed, 389 insertions(+), 243 deletions(-) create mode 100644 crates/optimism/CHANGELOG.md create mode 100644 crates/optimism/Cargo.toml create mode 100644 crates/optimism/LICENSE rename crates/{revm/src/optimism => optimism/src}/bn128.rs (94%) rename crates/{revm/src/optimism => optimism/src}/env.rs (97%) rename crates/{revm/src/optimism => optimism/src}/fast_lz.rs (96%) rename crates/{revm/src/optimism => optimism/src}/handler_register.rs (81%) rename crates/{revm/src/optimism => optimism/src}/l1block.rs (99%) rename crates/{revm/src/optimism.rs => optimism/src/lib.rs} (93%) rename crates/{revm/src/optimism => optimism/src}/result.rs (98%) rename crates/{revm/src/optimism => optimism/src}/spec.rs (87%) diff --git a/Cargo.lock b/Cargo.lock index 18b9cb11f9..06f27e920c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3108,7 +3108,6 @@ dependencies = [ "criterion", "derive-where", "dyn-clone", - "enumn", "ethers-contract", "ethers-core", "ethers-providers", @@ -3136,6 +3135,25 @@ dependencies = [ "walkdir", ] +[[package]] +name = "revm-optimism" +version = "1.0.0" +dependencies = [ + "alloy-provider", + "alloy-sol-types", + "anyhow", + "auto_impl", + "criterion", + "derive-where", + "dyn-clone", + "enumn", + "indicatif", + "revm", + "rstest", + "serde", + "serde_json", +] + [[package]] name = "revm-precompile" version = "11.0.1" diff --git a/Cargo.toml b/Cargo.toml index 426d6e403f..48b6ffe24b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "crates/primitives", "crates/interpreter", "crates/precompile", + "crates/optimism", ] resolver = "2" default-members = ["crates/revm"] @@ -15,7 +16,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [profile.release] -lto = true +#lto = true codegen-units = 1 debug = true diff --git a/bins/revm-test/src/bin/analysis.rs b/bins/revm-test/src/bin/analysis.rs index 76978fe56c..c71e50c863 100644 --- a/bins/revm-test/src/bin/analysis.rs +++ b/bins/revm-test/src/bin/analysis.rs @@ -1,13 +1,11 @@ use revm::{ - db::BenchmarkDB, + db::{BenchmarkDB, EthereumBenchmarkWiring}, interpreter::analysis::to_analysed, - primitives::{address, bytes, Bytecode, Bytes, EthereumWiring, TxKind}, + primitives::{address, bytes, Bytecode, Bytes, TxKind}, Evm, }; use std::time::Instant; -type EthereumBenchmarkWire = EthereumWiring; - fn main() { let contract_data : Bytes = hex::decode( "6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820df254047bc8f2904ad3e966b6db116d703bebd40efadadb5e738c836ffc8f58a0029").unwrap().into(); @@ -15,7 +13,7 @@ fn main() { let bytecode_analysed = to_analysed(Bytecode::new_raw(contract_data)); // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::::builder() + let mut evm = Evm::::builder() .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = address!("1000000000000000000000000000000000000000"); diff --git a/bins/revm-test/src/bin/burntpix/main.rs b/bins/revm-test/src/bin/burntpix/main.rs index bf170fa735..581f611204 100644 --- a/bins/revm-test/src/bin/burntpix/main.rs +++ b/bins/revm-test/src/bin/burntpix/main.rs @@ -28,7 +28,7 @@ sol! { } } -type EthereumBenchmarkWire = EthereumWiring, ()>; +type EthereumCacheDbWiring = EthereumWiring, ()>; fn main() { let (seed, iterations) = try_init_env_vars().expect("Failed to parse env vars"); @@ -37,7 +37,7 @@ fn main() { let db = init_db(); - let mut evm = Evm::::builder() + let mut evm = Evm::::builder() .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); tx.transact_to = TxKind::Call(BURNTPIX_MAIN_ADDRESS); diff --git a/bins/revm-test/src/bin/snailtracer.rs b/bins/revm-test/src/bin/snailtracer.rs index 53c662b790..3a874a44e0 100644 --- a/bins/revm-test/src/bin/snailtracer.rs +++ b/bins/revm-test/src/bin/snailtracer.rs @@ -1,17 +1,15 @@ use revm::{ - db::BenchmarkDB, + db::{BenchmarkDB, EthereumBenchmarkWiring}, interpreter::analysis::to_analysed, - primitives::{address, bytes, Bytecode, Bytes, EthereumWiring, TxKind}, + primitives::{address, bytes, Bytecode, Bytes, TxKind}, Evm, }; -type EthereumBenchmarkWire = EthereumWiring; - pub fn simple_example() { let bytecode = to_analysed(Bytecode::new_raw(CONTRACT_DATA.clone())); // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::::builder() + let mut evm = Evm::::builder() .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. diff --git a/bins/revm-test/src/bin/transfer.rs b/bins/revm-test/src/bin/transfer.rs index a257d1df3e..b0845fa34f 100644 --- a/bins/revm-test/src/bin/transfer.rs +++ b/bins/revm-test/src/bin/transfer.rs @@ -1,16 +1,13 @@ use revm::{ - db::BenchmarkDB, - primitives::{Bytecode, EthereumWiring, TxKind, U256}, + db::{BenchmarkDB, EthereumBenchmarkWiring}, + primitives::{Bytecode, TxKind, U256}, Evm, }; - use std::time::Duration; -type EthereumBenchmarkWire = EthereumWiring; - fn main() { // BenchmarkDB is dummy state that implements Database trait. - let mut evm = Evm::::builder() + let mut evm = Evm::::builder() .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 539efd39d4..3065280213 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -2,7 +2,7 @@ use revm::{ db::BenchmarkDB, inspector_handle_register, inspectors::TracerEip3155, - primitives::{address, Address, Bytecode,BytecodeDecodeError, EthereumWiring, TxKind}, + primitives::{address, Address, Bytecode, BytecodeDecodeError, EthereumWiring, TxKind}, Database, Evm, }; use std::io::Error as IoError; diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 617521919e..f5e36f40fb 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -29,8 +29,8 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; -type ExecEvmWiring<'a> = revm::primitives::EthereumWiring<&'a mut State, ()>; -type TraceEvmWiring<'a> = revm::primitives::EthereumWiring<&'a mut State, TracerEip3155>; +type ExecEvmWiring<'a> = EthereumWiring<&'a mut State, ()>; +type TraceEvmWiring<'a> = EthereumWiring<&'a mut State, TracerEip3155>; #[derive(Debug, Error)] #[error("Test {name} failed: {kind}")] diff --git a/crates/optimism/CHANGELOG.md b/crates/optimism/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml new file mode 100644 index 0000000000..a5b87d0209 --- /dev/null +++ b/crates/optimism/Cargo.toml @@ -0,0 +1,91 @@ +[package] +authors = ["Dragan Rakita "] +description = "Revm Optimism" +edition = "2021" +keywords = ["ethereum", "optimism", "evm", "revm", "no_std"] +license = "MIT" +name = "revm-optimism" +repository = "https://github.com/bluealloy/revm" +version = "1.0.0" +readme = "../../README.md" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unreachable_pub = "warn" +unused_must_use = "deny" +rust_2018_idioms = "deny" + +[lints.rustdoc] +all = "warn" + +[dependencies] +# revm +revm = { path = "../revm", version = "14.0.1", default-features = false } + +# misc +auto_impl = { version = "1.2", default-features = false } +derive-where = { version = "1.2.7", default-features = false } +dyn-clone = "1.0" +enumn = { version = "0.1"} + +# Optional +serde = { version = "1.0", default-features = false, features = [ + "derive", + "rc", +], optional = true } +serde_json = { version = "1.0", default-features = false, features = [ + "alloc", +], optional = true } + + +[dev-dependencies] +anyhow = "1.0.83" +criterion = "0.5" +indicatif = "0.17" +rstest = "0.22.0" +alloy-sol-types = "0.8" + +alloy-provider = "0.3" + +[features] +default = ["std", "c-kzg", "secp256k1", "portable", "blst"] +std = [ + "serde?/std", + "serde_json?/std", + "serde_json?/preserve_order", + "revm/std", +] +hashbrown = ["revm/hashbrown"] +serde = ["dep:serde", "revm/serde"] +serde-json = ["serde", "dep:serde_json"] +portable = ["revm/portable"] + + +dev = [ + "memory_limit", + "optional_balance_check", + "optional_block_gas_limit", + "optional_eip3607", + "optional_gas_refund", + "optional_no_base_fee", + "optional_beneficiary_reward", + "optional_nonce_check", +] +memory_limit = ["revm/memory_limit"] +optional_balance_check = ["revm/optional_balance_check"] +optional_block_gas_limit = ["revm/optional_block_gas_limit"] +optional_eip3607 = ["revm/optional_eip3607"] +optional_gas_refund = ["revm/optional_gas_refund"] +optional_no_base_fee = ["revm/optional_no_base_fee"] +optional_beneficiary_reward = ["revm/optional_beneficiary_reward"] +optional_nonce_check = ["revm/optional_nonce_check"] + +# See comments in `revm-precompile` +secp256k1 = ["revm/secp256k1"] +c-kzg = ["revm/c-kzg"] +# `kzg-rs` is not audited but useful for `no_std` environment, use it with causing and default to `c-kzg` if possible. +kzg-rs = ["revm/kzg-rs"] +blst = ["revm/blst"] diff --git a/crates/optimism/LICENSE b/crates/optimism/LICENSE new file mode 100644 index 0000000000..ad98ff22cc --- /dev/null +++ b/crates/optimism/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-2024 draganrakita + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/crates/revm/src/optimism/bn128.rs b/crates/optimism/src/bn128.rs similarity index 94% rename from crates/revm/src/optimism/bn128.rs rename to crates/optimism/src/bn128.rs index 5ad8e83f95..be5bee82fc 100644 --- a/crates/revm/src/optimism/bn128.rs +++ b/crates/optimism/src/bn128.rs @@ -1,5 +1,5 @@ -use revm_precompile::bn128; -use revm_precompile::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use revm::precompile::bn128; +use revm::precompile::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; pub(crate) mod pair { use super::*; @@ -25,7 +25,7 @@ pub(crate) mod pair { #[cfg(test)] mod tests { - use revm_precompile::primitives::{hex, PrecompileErrors}; + use revm::primitives::{hex, PrecompileErrors}; use super::*; diff --git a/crates/revm/src/optimism/env.rs b/crates/optimism/src/env.rs similarity index 97% rename from crates/revm/src/optimism/env.rs rename to crates/optimism/src/env.rs index 32863938aa..15467030f0 100644 --- a/crates/revm/src/optimism/env.rs +++ b/crates/optimism/src/env.rs @@ -1,4 +1,4 @@ -use crate::primitives::{ +use revm::primitives::{ AccessListItem, Address, AuthorizationList, Bytes, Transaction, TransactionValidation, TxKind, B256, U256, }; @@ -10,7 +10,7 @@ use super::{OptimismInvalidTransaction, OptimismTransaction}; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TxEnv { #[cfg_attr(feature = "serde", serde(flatten))] - pub base: crate::primitives::TxEnv, + pub base: revm::primitives::TxEnv, /// The source hash is used to make sure that deposit transactions do /// not have identical hashes. diff --git a/crates/revm/src/optimism/fast_lz.rs b/crates/optimism/src/fast_lz.rs similarity index 96% rename from crates/revm/src/optimism/fast_lz.rs rename to crates/optimism/src/fast_lz.rs index cf715bf3cb..22e8188caa 100644 --- a/crates/revm/src/optimism/fast_lz.rs +++ b/crates/optimism/src/fast_lz.rs @@ -105,14 +105,14 @@ fn u24(input: &[u8], idx: u32) -> u32 { #[cfg(test)] mod tests { + use super::*; + use crate::OptimismEvmWiring; use alloy_sol_types::sol; use alloy_sol_types::SolCall; - - use super::*; - use crate::db::BenchmarkDB; - use crate::{ - primitives::address, primitives::bytes, primitives::Bytecode, primitives::Bytes, - primitives::TxKind, primitives::U256, Evm, + use revm::{ + db::BenchmarkDB, + primitives::{address, bytes, Bytecode, Bytes, TxKind, U256}, + Evm, }; use rstest::rstest; @@ -162,12 +162,13 @@ mod tests { let native_val = flz_compress_len(&input); - let mut evm = Evm::builder() + let mut evm = Evm::>::builder() .with_db(BenchmarkDB::new_bytecode(contract_bytecode.clone())) .modify_tx_env(|tx| { - tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); - tx.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); + tx.base.caller = address!("1000000000000000000000000000000000000000"); + tx.base.transact_to = + TxKind::Call(address!("0000000000000000000000000000000000000000")); + tx.base.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); }) .build(); diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/optimism/src/handler_register.rs similarity index 81% rename from crates/revm/src/optimism/handler_register.rs rename to crates/optimism/src/handler_register.rs index 5908892843..bdcc16a2ce 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/optimism/src/handler_register.rs @@ -1,61 +1,58 @@ //! Handler related to Optimism chain -use crate::{ +use super::{ + optimism_spec_to_generic, OptimismContext, OptimismHaltReason, OptimismInvalidTransaction, + OptimismSpec, OptimismSpecId, OptimismTransaction, OptimismWiring, +}; +use crate::{BASE_FEE_RECIPIENT, L1_FEE_RECIPIENT}; +use core::ops::Mul; +use revm::{ handler::{ mainnet::{self, deduct_caller_inner}, register::EvmHandler, }, interpreter::{return_ok, return_revert, Gas, InstructionResult}, - optimism, optimism_spec_to_generic, + precompile::{secp256r1, PrecompileSpecId}, primitives::{ - db::Database, Account, Block, EVMError, EVMResultGeneric, Env, ExecutionResult, HashMap, - InvalidTransaction, ResultAndState, Transaction, U256, + db::Database, Account, Block, EVMError, EVMResult, EVMResultGeneric, EnvWiring, + ExecutionResult, HashMap, InvalidTransaction, ResultAndState, Transaction, U256, }, Context, ContextPrecompiles, FrameResult, }; -use core::ops::Mul; -use revm_precompile::{secp256r1, PrecompileSpecId}; use std::string::ToString; use std::sync::Arc; -use super::{ - OptimismContext, OptimismHaltReason, OptimismInvalidTransaction, OptimismSpec, OptimismSpecId, - OptimismTransaction, OptimismWiring, -}; - -pub fn optimism_handle_register( - handler: &mut EvmHandler<'_, EvmWiringT, EXT, DB>, -) where +pub fn optimism_handle_register(handler: &mut EvmHandler<'_, EvmWiringT>) +where EvmWiringT: OptimismWiring, - DB: Database, { optimism_spec_to_generic!(handler.spec_id, { // validate environment - handler.validation.env = Arc::new(validate_env::); + handler.validation.env = Arc::new(validate_env::); // Validate transaction against state. handler.validation.tx_against_state = - Arc::new(validate_tx_against_state::); + Arc::new(validate_tx_against_state::); // Load additional precompiles for the given chain spec. - handler.pre_execution.load_precompiles = - Arc::new(load_precompiles::); + handler.pre_execution.load_precompiles = Arc::new(load_precompiles::); // load l1 data - handler.pre_execution.load_accounts = Arc::new(load_accounts::); + handler.pre_execution.load_accounts = Arc::new(load_accounts::); // An estimated batch cost is charged from the caller and added to L1 Fee Vault. - handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); + handler.pre_execution.deduct_caller = Arc::new(deduct_caller::); // Refund is calculated differently then mainnet. - handler.execution.last_frame_return = Arc::new(last_frame_return::); - handler.post_execution.refund = Arc::new(refund::); - handler.post_execution.reward_beneficiary = Arc::new(reward_beneficiary::); + handler.execution.last_frame_return = Arc::new(last_frame_return::); + handler.post_execution.refund = Arc::new(refund::); + handler.post_execution.reward_beneficiary = + Arc::new(reward_beneficiary::); // In case of halt of deposit transaction return Error. - handler.post_execution.output = Arc::new(output::); - handler.post_execution.end = Arc::new(end::); + handler.post_execution.output = Arc::new(output::); + handler.post_execution.end = Arc::new(end::); }); } /// Validate environment for the Optimism chain. -pub fn validate_env( +pub fn validate_env( env: &EnvWiring, -) -> Result<(), EVMError> { +) -> EVMResultGeneric<(), EvmWiringT> { // Do not perform any extra validation for deposit transactions, they are pre-verified on L1. if env.tx.source_hash().is_some() { return Ok(()); @@ -78,26 +75,21 @@ pub fn validate_env( +pub fn validate_tx_against_state( context: &mut Context, -) -> Result<(), EVMError> { +) -> EVMResultGeneric<(), EvmWiringT> { if context.evm.inner.env.tx.source_hash().is_some() { return Ok(()); } - mainnet::validate_tx_against_state::(context) + mainnet::validate_tx_against_state::(context) } /// Handle output of the transaction #[inline] -pub fn last_frame_return( +pub fn last_frame_return( context: &mut Context, frame_result: &mut FrameResult, -) -> Result<(), EVMError> { +) -> EVMResultGeneric<(), EvmWiringT> { let env = context.evm.inner.env(); let is_deposit = env.tx.source_hash().is_some(); let tx_system = env.tx.is_system_transaction(); @@ -161,16 +153,16 @@ pub fn last_frame_return( - context: &mut Context, +pub fn refund( + context: &mut Context, gas: &mut Gas, eip7702_refund: i64, ) { gas.record_refund(eip7702_refund); let env = context.evm.inner.env(); - let is_deposit = env.tx.optimism.source_hash.is_some(); - let is_regolith = SPEC::enabled(REGOLITH); + let is_deposit = env.tx.source_hash().is_some(); + let is_regolith = SPEC::optimism_enabled(OptimismSpecId::REGOLITH); // Prior to Regolith, deposit transactions did not receive gas refunds. let is_gas_refund_disabled = env.cfg.is_gas_refund_disabled() || (is_deposit && !is_regolith); @@ -181,8 +173,8 @@ pub fn refund( /// Load precompiles for Optimism chain. #[inline] -pub fn load_precompiles( -) -> ContextPrecompiles { +pub fn load_precompiles( +) -> ContextPrecompiles { let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)); if SPEC::optimism_enabled(OptimismSpecId::FJORD) { @@ -192,10 +184,10 @@ pub fn load_precompiles( +pub fn load_accounts( context: &mut Context, -) -> EVMResultGeneric<(), EvmWiringT, DB::Error> { +) -> EVMResultGeneric<(), EvmWiringT> { // the L1-cost fee is only computed for Optimism non-deposit transactions. if context.evm.env.tx.source_hash().is_none() { @@ -218,14 +210,14 @@ fn load_accounts(context) + mainnet::load_accounts::(context) } /// Deduct max balance from caller #[inline] -pub fn deduct_caller( +pub fn deduct_caller( context: &mut Context, -) -> Result<(), EVMError> { +) -> EVMResultGeneric<(), EvmWiringT> { // load caller's account. let mut caller_account = context .evm @@ -260,6 +252,7 @@ pub fn deduct_caller( +pub fn reward_beneficiary( context: &mut Context, gas: &Gas, -) -> Result<(), EVMError> { +) -> EVMResultGeneric<(), EvmWiringT> { let is_deposit = context.evm.inner.env.tx.source_hash().is_some(); // transfer fee to coinbase/beneficiary. if !is_deposit { - mainnet::reward_beneficiary::(context, gas)?; + mainnet::reward_beneficiary::(context, gas)?; } if !is_deposit { @@ -313,7 +306,7 @@ pub fn reward_beneficiary( +pub fn output( context: &mut Context, frame_result: FrameResult, -) -> Result, EVMError> { - let result = mainnet::output::(context, frame_result)?; +) -> EVMResult { + let result = mainnet::output::(context, frame_result)?; if result.result.is_halt() { // Post-regolith, if the transaction is a deposit transaction and it halts, @@ -361,10 +354,10 @@ pub fn output /// Optimism end handle changes output if the transaction is a deposit transaction. /// Deposit transaction can't be reverted and is always successful. #[inline] -pub fn end( +pub fn end( context: &mut Context, - evm_output: Result, EVMError>, -) -> Result, EVMError> { + evm_output: EVMResult, +) -> EVMResult { evm_output.or_else(|err| { if matches!(err, EVMError::Transaction(_)) && context.evm.inner.env().tx.source_hash().is_some() @@ -428,26 +421,27 @@ pub fn end( #[cfg(test)] mod tests { - use revm_interpreter::{CallOutcome, InterpreterResult}; - use super::*; - use crate::{ + use crate::{BedrockSpec, L1BlockInfo, LatestSpec, OptimismEvmWiring, RegolithSpec}; + use revm::{ db::{EmptyDB, InMemoryDB}, - optimism::{self, BedrockSpec, LatestSpec, RegolithSpec}, - primitives::{bytes, state::AccountInfo, Address, Bytes, Env, B256}, - L1BlockInfo, + interpreter::{CallOutcome, InterpreterResult}, + primitives::{bytes, state::AccountInfo, Address, Bytes, B256}, }; + type TestEmptyOpWiring = OptimismEvmWiring; + type TestMemOpWiring = OptimismEvmWiring; + /// Creates frame result. fn call_last_frame_return( - env: Env, + env: EnvWiring, instruction_result: InstructionResult, gas: Gas, ) -> Gas where SPEC: OptimismSpec, { - let mut ctx = Context::new_empty(); + let mut ctx = Context::::new_with_db(EmptyDB::default()); ctx.evm.inner.env = Box::new(env); let mut first_frame = FrameResult::Call(CallOutcome::new( InterpreterResult { @@ -457,14 +451,14 @@ mod tests { }, 0..0, )); - last_frame_return::(&mut ctx, &mut first_frame).unwrap(); - refund::(&mut ctx, first_frame.gas_mut(), 0); + last_frame_return::(&mut ctx, &mut first_frame).unwrap(); + refund::(&mut ctx, first_frame.gas_mut(), 0); *first_frame.gas() } #[test] fn test_revert_gas() { - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = None; @@ -477,7 +471,7 @@ mod tests { #[test] fn test_consume_gas() { - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -490,7 +484,7 @@ mod tests { #[test] fn test_consume_gas_with_refund() { - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -511,7 +505,7 @@ mod tests { #[test] fn test_consume_gas_sys_deposit_tx() { - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.base.gas_limit = 100; env.tx.source_hash = Some(B256::ZERO); @@ -533,7 +527,7 @@ mod tests { }, ); - let mut context: Context = Context::new_with_db(db); + let mut context = Context::::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -545,7 +539,7 @@ mod tests { // added mint value is 10. context.evm.inner.env.tx.mint = Some(10); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let account = context @@ -568,7 +562,7 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); + let mut context = Context::::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -583,7 +577,7 @@ mod tests { // so enveloped_tx gas cost is ignored. context.evm.inner.env.tx.source_hash = Some(B256::ZERO); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let account = context @@ -606,7 +600,7 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); + let mut context = Context::::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -615,7 +609,7 @@ mod tests { }); // l1block cost is 1048 fee. context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); - deduct_caller::(&mut context).unwrap(); + deduct_caller::(&mut context).unwrap(); // Check the account balance is updated. let account = context @@ -638,7 +632,7 @@ mod tests { ..Default::default() }, ); - let mut context: Context = Context::new_with_db(db); + let mut context = Context::::new_with_db(db); *context.evm.chain.l1_block_info_mut() = Some(L1BlockInfo { l1_base_fee: U256::from(1_000), l1_fee_overhead: Some(U256::from(1_000)), @@ -649,7 +643,7 @@ mod tests { context.evm.inner.env.tx.enveloped_tx = Some(bytes!("FACADE")); assert_eq!( - deduct_caller::(&mut context), + deduct_caller::(&mut context), Err(EVMError::Transaction( InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(U256::from(1048)), @@ -663,34 +657,34 @@ mod tests { #[test] fn test_validate_sys_tx() { // mark the tx as a system transaction. - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.is_system_transaction = Some(true); assert_eq!( - validate_env::(&env), + validate_env::(&env), Err(EVMError::Transaction( OptimismInvalidTransaction::DepositSystemTxPostRegolith )) ); // Pre-regolith system transactions should be allowed. - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_deposit_tx() { // Set source hash. - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.source_hash = Some(B256::ZERO); - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } #[test] fn test_validate_tx_against_state_deposit_tx() { // Set source hash. - let mut env = Env::::default(); + let mut env = EnvWiring::::default(); env.tx.source_hash = Some(B256::ZERO); // Nonce and balance checks should be skipped for deposit transactions. - assert!(validate_env::(&env).is_ok()); + assert!(validate_env::(&env).is_ok()); } } diff --git a/crates/revm/src/optimism/l1block.rs b/crates/optimism/src/l1block.rs similarity index 99% rename from crates/revm/src/optimism/l1block.rs rename to crates/optimism/src/l1block.rs index db4929e304..5ae56a0a31 100644 --- a/crates/revm/src/optimism/l1block.rs +++ b/crates/optimism/src/l1block.rs @@ -1,6 +1,6 @@ -use crate::optimism::fast_lz::flz_compress_len; -use crate::primitives::{address, db::Database, Address, U256}; +use crate::fast_lz::flz_compress_len; use core::ops::Mul; +use revm::primitives::{address, db::Database, Address, U256}; use super::OptimismSpecId; @@ -249,7 +249,7 @@ impl L1BlockInfo { #[cfg(test)] mod tests { use super::*; - use crate::primitives::bytes; + use revm::primitives::bytes; #[test] fn test_data_gas_non_zero_bytes() { diff --git a/crates/revm/src/optimism.rs b/crates/optimism/src/lib.rs similarity index 93% rename from crates/revm/src/optimism.rs rename to crates/optimism/src/lib.rs index ba14edc211..03a4572eaf 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/optimism/src/lib.rs @@ -1,13 +1,13 @@ //! Optimism-specific constants, types, and helpers. mod bn128; +mod env; mod fast_lz; mod handler_register; mod l1block; mod result; mod spec; -use crate::primitives::{Bytes, TransactionValidation, B256}; pub use handler_register::{ deduct_caller, end, last_frame_return, load_accounts, load_precompiles, optimism_handle_register, output, refund, reward_beneficiary, validate_env, @@ -15,6 +15,7 @@ pub use handler_register::{ }; pub use l1block::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; pub use result::{OptimismHaltReason, OptimismInvalidTransaction}; +use revm::primitives::{Bytes, TransactionValidation, B256}; pub use spec::*; pub trait OptimismContext { @@ -55,8 +56,8 @@ pub trait OptimismTransaction { /// Trait for an Optimism chain spec. pub trait OptimismWiring: - crate::EvmWiring< - Context: OptimismContext, + revm::EvmWiring< + ChainContext: OptimismContext, Hardfork = OptimismSpecId, HaltReason = OptimismHaltReason, Transaction: OptimismTransaction @@ -66,8 +67,8 @@ pub trait OptimismWiring: } impl OptimismWiring for EvmWiringT where - EvmWiringT: crate::EvmWiring< - Context: OptimismContext, + EvmWiringT: revm::EvmWiring< + ChainContext: OptimismContext, Hardfork = OptimismSpecId, HaltReason = OptimismHaltReason, Transaction: OptimismTransaction diff --git a/crates/revm/src/optimism/result.rs b/crates/optimism/src/result.rs similarity index 98% rename from crates/revm/src/optimism/result.rs rename to crates/optimism/src/result.rs index 94a0d9ec1b..9b5227669e 100644 --- a/crates/revm/src/optimism/result.rs +++ b/crates/optimism/src/result.rs @@ -1,6 +1,6 @@ use core::fmt::Display; -use crate::primitives::{EVMError, HaltReason, InvalidTransaction}; +use revm::primitives::{EVMError, HaltReason, InvalidTransaction}; /// Optimism transaction validation error. #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/revm/src/optimism/spec.rs b/crates/optimism/src/spec.rs similarity index 87% rename from crates/revm/src/optimism/spec.rs rename to crates/optimism/src/spec.rs index add7fcd482..5dfe9e4e37 100644 --- a/crates/revm/src/optimism/spec.rs +++ b/crates/optimism/src/spec.rs @@ -1,34 +1,36 @@ -use revm_precompile::PrecompileSpecId; - -use crate::{ - handler::register::HandleRegisters, - primitives::{db::Database, BlockEnv, Spec, SpecId}, - EvmHandler, L1BlockInfo, +use core::marker::PhantomData; +use revm::{ + handler::register::HandleRegisters,precompile::PrecompileSpecId, + primitives::{db::Database,EvmWiring, BlockEnv, Spec, SpecId}, + EvmHandler, }; - -use super::{env::TxEnv, OptimismContext, OptimismHaltReason}; +use crate::{env::TxEnv,L1BlockInfo, optimism_handle_register, OptimismContext, OptimismHaltReason}; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct EvmWiring; +pub struct OptimismEvmWiring { + _phantom: PhantomData<(DB,EXT)>, +} -impl crate::primitives::EvmWiring for EvmWiring { +impl EvmWiring for OptimismEvmWiring { type Block = BlockEnv; + type Database = DB; + type ChainContext = Context; + type ExternalContext = EXT; type Hardfork = OptimismSpecId; type HaltReason = OptimismHaltReason; type Transaction = TxEnv; } -impl crate::EvmWiring for EvmWiring { - type Context = Context; +impl revm::EvmWiring for OptimismEvmWiring { - fn handler<'evm, EXT, DB>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self, EXT, DB> + fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self> where DB: Database, { let mut handler = EvmHandler::mainnet_with_spec(hardfork); handler.append_handler_register(HandleRegisters::Plain( - crate::optimism::optimism_handle_register::, + optimism_handle_register::, )); handler @@ -36,7 +38,7 @@ impl crate::EvmWiring for EvmWiring { } /// Context for the Optimism chain. -#[derive(Default)] +#[derive(Clone, Default, Debug, PartialEq, Eq)] pub struct Context { l1_block_info: Option, } @@ -80,8 +82,9 @@ pub enum OptimismSpecId { CANCUN = 20, ECOTONE = 21, FJORD = 22, - PRAGUE = 23, - PRAGUE_EOF = 24, + GRANITE = 23, + PRAGUE = 24, + PRAGUE_EOF = 25, #[default] LATEST = u8::MAX, } @@ -127,7 +130,7 @@ impl OptimismSpecId { SpecId::MERGE } OptimismSpecId::SHANGHAI | OptimismSpecId::CANYON => SpecId::SHANGHAI, - OptimismSpecId::CANCUN | OptimismSpecId::ECOTONE | OptimismSpecId::FJORD => { + OptimismSpecId::CANCUN | OptimismSpecId::ECOTONE | OptimismSpecId::FJORD |OptimismSpecId::GRANITE => { SpecId::CANCUN } OptimismSpecId::PRAGUE => SpecId::PRAGUE, @@ -180,13 +183,14 @@ impl From for PrecompileSpecId { /// String identifiers for Optimism hardforks. pub mod id { // Re-export the Ethereum hardforks. - pub use crate::primitives::specification::id::*; + pub use revm::primitives::specification::id::*; pub const BEDROCK: &str = "Bedrock"; pub const REGOLITH: &str = "Regolith"; pub const CANYON: &str = "Canyon"; pub const ECOTONE: &str = "Ecotone"; pub const FJORD: &str = "Fjord"; + pub const GRANITE: &str = "Granite"; } impl From<&str> for OptimismSpecId { @@ -251,6 +255,7 @@ impl From for &'static str { OptimismSpecId::CANYON => id::CANYON, OptimismSpecId::ECOTONE => id::ECOTONE, OptimismSpecId::FJORD => id::FJORD, + OptimismSpecId::GRANITE => id::GRANITE, OptimismSpecId::LATEST => id::LATEST, } } @@ -311,96 +316,101 @@ spec!(REGOLITH, RegolithSpec); spec!(CANYON, CanyonSpec); spec!(ECOTONE, EcotoneSpec); spec!(FJORD, FjordSpec); +spec!(GRANITE, GraniteSpec); #[macro_export] macro_rules! optimism_spec_to_generic { ($spec_id:expr, $e:expr) => {{ // We are transitioning from var to generic spec. match $spec_id { - $crate::optimism::OptimismSpecId::FRONTIER - | $crate::optimism::OptimismSpecId::FRONTIER_THAWING => { - use $crate::optimism::FrontierSpec as SPEC; + $crate::OptimismSpecId::FRONTIER + | $crate::OptimismSpecId::FRONTIER_THAWING => { + use $crate::FrontierSpec as SPEC; + $e + } + $crate::OptimismSpecId::HOMESTEAD + | $crate::OptimismSpecId::DAO_FORK => { + use $crate::HomesteadSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::HOMESTEAD - | $crate::optimism::OptimismSpecId::DAO_FORK => { - use $crate::optimism::HomesteadSpec as SPEC; + $crate::OptimismSpecId::TANGERINE => { + use $crate::TangerineSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::TANGERINE => { - use $crate::optimism::TangerineSpec as SPEC; + $crate::OptimismSpecId::SPURIOUS_DRAGON => { + use $crate::SpuriousDragonSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::SPURIOUS_DRAGON => { - use $crate::optimism::SpuriousDragonSpec as SPEC; + $crate::OptimismSpecId::BYZANTIUM => { + use $crate::ByzantiumSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::BYZANTIUM => { - use $crate::optimism::ByzantiumSpec as SPEC; + $crate::OptimismSpecId::PETERSBURG + | $crate::OptimismSpecId::CONSTANTINOPLE => { + use $crate::PetersburgSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::PETERSBURG - | $crate::optimism::OptimismSpecId::CONSTANTINOPLE => { - use $crate::optimism::PetersburgSpec as SPEC; + $crate::OptimismSpecId::ISTANBUL + | $crate::OptimismSpecId::MUIR_GLACIER => { + use $crate::IstanbulSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::ISTANBUL - | $crate::optimism::OptimismSpecId::MUIR_GLACIER => { - use $crate::optimism::IstanbulSpec as SPEC; + $crate::OptimismSpecId::BERLIN => { + use $crate::BerlinSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::BERLIN => { - use $crate::optimism::BerlinSpec as SPEC; + $crate::OptimismSpecId::LONDON + | $crate::OptimismSpecId::ARROW_GLACIER + | $crate::OptimismSpecId::GRAY_GLACIER => { + use $crate::LondonSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::LONDON - | $crate::optimism::OptimismSpecId::ARROW_GLACIER - | $crate::optimism::OptimismSpecId::GRAY_GLACIER => { - use $crate::optimism::LondonSpec as SPEC; + $crate::OptimismSpecId::MERGE => { + use $crate::MergeSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::MERGE => { - use $crate::optimism::MergeSpec as SPEC; + $crate::OptimismSpecId::SHANGHAI => { + use $crate::ShanghaiSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::SHANGHAI => { - use $crate::optimism::ShanghaiSpec as SPEC; + $crate::OptimismSpecId::CANCUN => { + use $crate::CancunSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::CANCUN => { - use $crate::optimism::CancunSpec as SPEC; + $crate::OptimismSpecId::LATEST => { + use $crate::LatestSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::LATEST => { - use $crate::optimism::LatestSpec as SPEC; + $crate::OptimismSpecId::PRAGUE => { + use $crate::PragueSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::PRAGUE => { - use $crate::optimism::PragueSpec as SPEC; + $crate::OptimismSpecId::PRAGUE_EOF => { + use $crate::PragueEofSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::PRAGUE_EOF => { - use $crate::optimism::PragueEofSpec as SPEC; + $crate::OptimismSpecId::BEDROCK => { + use $crate::BedrockSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::BEDROCK => { - use $crate::optimism::BedrockSpec as SPEC; + $crate::OptimismSpecId::REGOLITH => { + use $crate::RegolithSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::REGOLITH => { - use $crate::optimism::RegolithSpec as SPEC; + $crate::OptimismSpecId::CANYON => { + use $crate::CanyonSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::CANYON => { - use $crate::optimism::CanyonSpec as SPEC; + $crate::OptimismSpecId::GRANITE => { + use $crate::GraniteSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::ECOTONE => { - use $crate::optimism::EcotoneSpec as SPEC; + $crate::OptimismSpecId::ECOTONE => { + use $crate::EcotoneSpec as SPEC; $e } - $crate::optimism::OptimismSpecId::FJORD => { - use $crate::optimism::FjordSpec as SPEC; + $crate::OptimismSpecId::FJORD => { + use $crate::FjordSpec as SPEC; $e } } @@ -513,7 +523,6 @@ mod tests { OptimismSpecId::LATEST, assert_eq!(SPEC::SPEC_ID, SpecId::LATEST) ); - optimism_spec_to_generic!( OptimismSpecId::FRONTIER, assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::FRONTIER) @@ -606,6 +615,10 @@ mod tests { OptimismSpecId::FJORD, assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::FJORD) ); + optimism_spec_to_generic!( + OptimismSpecId::GRANITE, + assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::GRANITE) + ); optimism_spec_to_generic!( OptimismSpecId::PRAGUE, assert_eq!(SPEC::OPTIMISM_SPEC_ID, OptimismSpecId::PRAGUE) diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 6d616e1f55..6c42e67878 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,5 +1,8 @@ use crate::{ - calc_blob_gasprice, AccessListItem, Account, Address, AuthorizationList, Block, Bytes, EvmWiring, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, B256, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG + calc_blob_gasprice, AccessListItem, Account, Address, AuthorizationList, Block, Bytes, + EvmWiring, InvalidHeader, InvalidTransaction, Spec, SpecId, Transaction, TransactionValidation, + B256, MAX_BLOB_NUMBER_PER_BLOCK, MAX_CODE_SIZE, MAX_INITCODE_SIZE, U256, + VERSIONED_HASH_VERSION_KZG, }; use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; diff --git a/crates/primitives/src/evm_wiring.rs b/crates/primitives/src/evm_wiring.rs index c987f6cdab..88adb7ea68 100644 --- a/crates/primitives/src/evm_wiring.rs +++ b/crates/primitives/src/evm_wiring.rs @@ -32,9 +32,12 @@ pub trait TransactionValidation { } pub trait EvmWiring: Sized { - /// External type + /// External context type type ExternalContext: Sized; + /// Chain context type. + type ChainContext: Sized + Default + Debug; + /// Database type. type Database: Database; @@ -59,6 +62,7 @@ pub struct EthereumWiring { impl EvmWiring for EthereumWiring { type Database = DB; type ExternalContext = EXT; + type ChainContext = (); type Block = crate::BlockEnv; type Transaction = crate::TxEnv; type Hardfork = SpecId; diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index aa667a10c4..40f74977d6 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -30,7 +30,6 @@ revm-precompile = { path = "../precompile", version = "11.0.1", default-features auto_impl = { version = "1.2", default-features = false } derive-where = { version = "1.2.7", default-features = false } dyn-clone = "1.0" -enumn = { version = "0.1", optional = true } # Optional serde = { version = "1.0", default-features = false, features = [ @@ -85,8 +84,6 @@ portable = ["revm-precompile/portable", "revm-interpreter/portable"] test-utils = [] -optimism = ["dep:enumn", "revm-interpreter/optimism", "revm-precompile/optimism"] - ethersdb = ["std", "dep:tokio", "dep:ethers-providers", "dep:ethers-core"] alloydb = [ @@ -143,10 +140,10 @@ required-features = ["std", "serde-json"] #path = "../../examples/uniswap_v2_usdc_swap.rs" #required-features = ["alloydb"] -[[example]] -name = "custom_opcodes" -path = "../../examples/custom_opcodes.rs" -required-features = [] +#[[example]] +#name = "custom_opcodes" +#path = "../../examples/custom_opcodes.rs" +#required-features = [] [[bench]] name = "bench" diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index feed985f61..c4fd5231a7 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -22,7 +22,7 @@ use crate::{ use std::boxed::Box; /// Main Context structure that contains both EvmContext and External context. -#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::Transaction, EvmWiringT::Database, ::Error, EvmWiringT::ExternalContext)] +#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::ChainContext, EvmWiringT::Transaction, EvmWiringT::Database, ::Error, EvmWiringT::ExternalContext)] pub struct Context { /// Evm Context (internal context). pub evm: EvmContext, @@ -39,13 +39,13 @@ impl Default for Context> { } } -impl Context +impl Context where EvmWiringT: - EvmWiring, + EvmWiring, { /// Creates new context with database. - pub fn new_with_db(db: EvmWiringT::Database) -> Context { + pub fn new_with_db(db: DB) -> Context { Context { evm: EvmContext::new_with_env(db, Box::default()), external: (), @@ -64,7 +64,7 @@ impl Context { } /// Context with handler configuration. -#[derive_where(Clone; EvmWiringT::Block , EvmWiringT::Transaction,EvmWiringT::Database, ::Error, EvmWiringT::ExternalContext)] +#[derive_where(Clone; EvmWiringT::Block, EvmWiringT::ChainContext, EvmWiringT::Transaction,EvmWiringT::Database, ::Error, EvmWiringT::ExternalContext)] pub struct ContextWithEvmWiring { /// Context of execution. pub context: Context, diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index a5e645ff11..bc7df8a67c 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -21,7 +21,7 @@ use core::ops::{Deref, DerefMut}; use std::{boxed::Box, sync::Arc}; /// EVM context that contains the inner EVM context and precompiles. -#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Transaction, EvmWiringT::Database, ::Error)] +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::ChainContext, EvmWiringT::Transaction, EvmWiringT::Database, ::Error)] pub struct EvmContext { /// Inner EVM context. pub inner: InnerEvmContext, @@ -522,6 +522,7 @@ pub(crate) mod test_utils { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), db, + chain: Default::default(), error: Ok(()), }, precompiles: ContextPrecompiles::default(), @@ -538,6 +539,7 @@ pub(crate) mod test_utils { env, journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), db, + chain: Default::default(), error: Ok(()), }, precompiles: ContextPrecompiles::default(), diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 457e94f6b1..8ce88ef030 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -18,7 +18,7 @@ use crate::{ use std::{boxed::Box, sync::Arc}; /// EVM contexts contains data that EVM needs for execution. -#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Transaction, EvmWiringT::Database, ::Error)] +#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::ChainContext, EvmWiringT::Transaction, EvmWiringT::Database, ::Error)] pub struct InnerEvmContext { /// EVM Environment contains all the information about config, block and transaction that /// evm needs. @@ -27,6 +27,8 @@ pub struct InnerEvmContext { pub journaled_state: JournaledState, /// Database to load data from. pub db: EvmWiringT::Database, + /// Inner context. + pub chain: EvmWiringT::ChainContext, /// Error that happened during execution. pub error: Result<(), ::Error>, } @@ -40,6 +42,7 @@ where env: Box::default(), journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), db, + chain: Default::default(), error: Ok(()), } } @@ -53,6 +56,7 @@ impl InnerEvmContext { env, journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), db, + chain: Default::default(), error: Ok(()), } } @@ -71,6 +75,7 @@ impl InnerEvmContext { env: self.env, journaled_state: self.journaled_state, db, + chain: Default::default(), error: Ok(()), } } @@ -155,7 +160,10 @@ impl InnerEvmContext { /// Return account balance and is_cold flag. #[inline] - pub fn balance(&mut self, address: Address) -> Result, ::Error> { + pub fn balance( + &mut self, + address: Address, + ) -> Result, ::Error> { self.journaled_state .load_account(address, &mut self.db) .map(|acc| acc.map(|a| a.info.balance)) @@ -168,7 +176,7 @@ impl InnerEvmContext { pub fn code( &mut self, address: Address, - ) -> Result,::Error> { + ) -> Result, ::Error> { let a = self.journaled_state.load_code(address, &mut self.db)?; // SAFETY: safe to unwrap as load_code will insert code if it is empty. let code = a.info.code.as_ref().unwrap(); diff --git a/crates/revm/src/db/in_memory_db.rs b/crates/revm/src/db/in_memory_db.rs index 58ab9ba1ba..c77efefa57 100644 --- a/crates/revm/src/db/in_memory_db.rs +++ b/crates/revm/src/db/in_memory_db.rs @@ -1,7 +1,7 @@ use super::{DatabaseCommit, DatabaseRef, EmptyDB}; use crate::primitives::{ - hash_map::Entry, Account, AccountInfo, Address, Bytecode, HashMap, Log, B256, KECCAK_EMPTY, - U256, + hash_map::Entry, Account, AccountInfo, Address, Bytecode, EthereumWiring, HashMap, Log, B256, + KECCAK_EMPTY, U256, }; use crate::Database; use core::convert::Infallible; @@ -356,6 +356,9 @@ impl AccountState { } } +/// Ethereum benchmark wiring +pub type EthereumBenchmarkWiring = EthereumWiring; + /// Custom benchmarking DB that only has account info for the zero address. /// /// Any other address will return an empty account. diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 061d568932..fc1ffd0a01 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -21,8 +21,6 @@ mod frame; pub mod handler; mod inspector; mod journaled_state; -#[cfg(feature = "optimism")] -pub mod optimism; // Export items. @@ -42,10 +40,6 @@ pub use frame::{CallFrame, CreateFrame, Frame, FrameData, FrameOrResult, FrameRe pub use handler::{register::EvmHandler, Handler}; pub use inspector::{inspector_handle_register, inspectors, GetInspector, Inspector}; pub use journaled_state::{JournalCheckpoint, JournalEntry, JournaledState}; -// export Optimism types, helpers, and constants -#[cfg(feature = "optimism")] -pub use optimism::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; - // Reexport libraries #[doc(inline)] diff --git a/examples/db_by_ref.rs b/examples/db_by_ref.rs index 76f50ab8de..a1088e04ab 100644 --- a/examples/db_by_ref.rs +++ b/examples/db_by_ref.rs @@ -1,9 +1,10 @@ +use core::fmt::Debug; use revm::{ db::{CacheDB, EmptyDB, WrapDatabaseRef}, handler::register::HandleRegister, inspector_handle_register, inspectors::{NoOpInspector, TracerEip3155}, - primitives::{EthereumWiring, ResultAndState}, + primitives::{EthereumWiring, HaltReason, ResultAndState}, DatabaseCommit, DatabaseRef, Evm, }; use std::error::Error; @@ -20,13 +21,13 @@ where type DBError = DBError; } -fn run_transaction( +fn run_transaction( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, -) -> anyhow::Result<(ResultAndState, DB)> { - let mut evm = Evm::builder() - .with_ref_db(db) + register_handles_fn: HandleRegister, EXT>>, +) -> anyhow::Result<(ResultAndState, DB)> { + let mut evm = Evm::>::builder() + .with_db(WrapDatabaseRef(db)) .with_external_context(ext) .append_handler_register(register_handles_fn) .build(); @@ -35,10 +36,10 @@ fn run_transaction( Ok((result, evm.into_context().evm.inner.db.0)) } -fn run_transaction_and_commit_with_ext( +fn run_transaction_and_commit_with_ext( db: DB, ext: EXT, - register_handles_fn: HandleRegister>, + register_handles_fn: HandleRegister, EXT>>, ) -> anyhow::Result<()> { // To circumvent borrow checker issues, we need to move the database into the // transaction and return it after the transaction is done. @@ -54,8 +55,8 @@ fn run_transaction_and_commit(db: &mut CacheDB) -> anyhow::Result<()> { let ResultAndState { state: changes, .. } = { let rdb = &*db; - let mut evm = Evm::builder() - .with_ref_db(rdb) + let mut evm = Evm::>::builder() + .with_db(WrapDatabaseRef(rdb)) .with_external_context(NoOpInspector) .append_handler_register(inspector_handle_register) .build(); diff --git a/examples/fork_ref_transact.rs b/examples/fork_ref_transact.rs index 014e2b1941..99614267d8 100644 --- a/examples/fork_ref_transact.rs +++ b/examples/fork_ref_transact.rs @@ -1,6 +1,7 @@ use alloy_sol_types::sol; use alloy_sol_types::SolCall; use ethers_providers::{Http, Provider}; +use revm::primitives::EthereumWiring; use revm::{ db::{CacheDB, EmptyDB, EthersDB}, primitives::{address, ExecutionResult, Output, TxKind, U256}, @@ -63,7 +64,7 @@ async fn main() -> anyhow::Result<()> { .unwrap(); // initialise an empty (default) EVM - let mut evm = Evm::builder() + let mut evm = Evm::, ()>>::builder() .with_db(cache_db) .modify_tx_env(|tx| { // fill in missing bits of env struct diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index 099d24ddbb..59cce05edf 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -6,7 +6,7 @@ use ethers_providers::{Http, Provider}; use indicatif::ProgressBar; use revm::db::{CacheDB, EthersDB, StateBuilder}; use revm::inspectors::TracerEip3155; -use revm::primitives::{AccessListItem, Address, TxKind, B256, U256}; +use revm::primitives::{AccessListItem, Address, EthereumWiring, TxKind, B256, U256}; use revm::{inspector_handle_register, Evm}; use std::fs::OpenOptions; use std::io::BufWriter; @@ -75,7 +75,7 @@ async fn main() -> anyhow::Result<()> { let state_db = EthersDB::new(client, Some(prev_id)).expect("panic"); let cache_db: CacheDB>> = CacheDB::new(state_db); let mut state = StateBuilder::new_with_database(cache_db).build(); - let mut evm = Evm::builder() + let mut evm = Evm::>::builder() .with_db(&mut state) .with_external_context(TracerEip3155::new(Box::new(std::io::stdout()))) .modify_block_env(|b| { From 897f8edd99537f8eec18b5db4f699623d980ed3e Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 4 Sep 2024 14:46:24 +0200 Subject: [PATCH 45/59] wip builder --- crates/optimism/Cargo.toml | 2 +- crates/revm/src/builder.rs | 49 ++++++++++++----------------------- crates/revm/src/chain_spec.rs | 8 +++--- 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index a5b87d0209..3a9e374743 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -23,7 +23,7 @@ all = "warn" [dependencies] # revm -revm = { path = "../revm", version = "14.0.1", default-features = false } +revm = { path = "../revm", version = "14.0.1", default-features = false, features=["std"] } # misc auto_impl = { version = "1.2", default-features = false } diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index f69a84a070..00d51f44f9 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -10,39 +10,36 @@ use std::boxed::Box; /// Evm Builder allows building or modifying EVM. /// Note that some of the methods that changes underlying structures /// will reset the registered handler to default mainnet. -pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring> { +pub struct EvmBuilder<'a, EvmWiringT: EvmWiring> { database: Option, external_context: Option, env: Option>>, /// Handler that will be used by EVM. It contains handle registers handler: Handler<'a, EvmWiringT, Context>, - /// Phantom data to mark the stage of the builder. - phantom: PhantomData, } -/// First stage of the builder allows setting generic variables. -/// Generic variables are database and external context. -pub struct SetGenericStage; +// /// First stage of the builder allows setting generic variables. +// /// Generic variables are database and external context. +// pub struct SetGenericStage; -/// Second stage of the builder allows appending handler registers. -/// Requires the database and external context to be set. -pub struct HandlerStage; +// /// Second stage of the builder allows appending handler registers. +// /// Requires the database and external context to be set. +// pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring> { +impl<'a> Default for EvmBuilder<'a, EthereumWiring> { fn default() -> Self { Self::new() } } -impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, EvmWiringT> { /// Sets the [`EvmWiring`] that will be used by [`Evm`]. - pub fn new() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { + pub fn new() -> EvmBuilder<'a, EvmWiringT> { EvmBuilder { database: None, external_context: None, env: None, handler: EvmWiringT::handler::<'a>(EvmWiringT::Hardfork::default()), - phantom: PhantomData, } } @@ -57,7 +54,6 @@ impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { external_context: Some(external_context), env: Some(env), handler, - phantom: PhantomData, } } @@ -69,7 +65,6 @@ impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { external_context: None, env: None, handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), - phantom: PhantomData, } } @@ -335,7 +330,7 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi /// Allows modification of Evm Database. pub fn modify_db(mut self, f: impl FnOnce(&mut EvmWiringT::Database)) -> Self { - f(&mut self.database.as_mut().unwrap()); + f(self.database.as_mut().unwrap()); self } @@ -344,13 +339,13 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi mut self, f: impl FnOnce(&mut EvmWiringT::ExternalContext), ) -> Self { - f(&mut self.external_context.as_mut().unwrap()); + f(self.external_context.as_mut().unwrap()); self } /// Allows modification of Evm Environment. pub fn modify_env(mut self, f: impl FnOnce(&mut Box>)) -> Self { - f(&mut self.env.as_mut().unwrap()); + f(self.env.as_mut().unwrap()); self } @@ -451,21 +446,11 @@ where #[cfg(test)] mod test { use crate::{ - db::EmptyDB, - inspector::inspector_handle_register, - inspectors::NoOpInspector, - primitives::{ - address, AccountInfo, Address, Bytecode, Bytes, EthereumWiring, PrecompileResult, - SpecId, TxKind, U256, - }, - Context, ContextPrecompile, ContextStatefulPrecompile, Evm, InMemoryDB, InnerEvmContext, + interpreter::Interpreter, + primitives::{address, AccountInfo, Bytecode, EthereumWiring, TxKind, U256}, + Context, Evm, InMemoryDB, }; - use alloy_provider::network::Ethereum; - use revm_interpreter::{gas, Host, Interpreter}; - use revm_precompile::PrecompileOutput; - use std::{cell::RefCell, rc::Rc, sync::Arc}; - - type TestEvmWiring = crate::primitives::DefaultEthereumWiring; + use std::{cell::RefCell, rc::Rc}; /// Custom evm context #[derive(Default, Clone, Debug)] diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index 437dc71f40..baf2b53eb5 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -1,8 +1,5 @@ use crate::{ - handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, - interpreter::opcode::InstructionTables, - primitives::{db::Database, spec_to_generic, EthereumWiring, EvmWiring as PrimitiveEvmWiring}, - EvmHandler, + handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, interpreter::opcode::InstructionTables, primitives::{db::Database, spec_to_generic, EthereumWiring, EvmWiring as PrimitiveEvmWiring}, EvmBuilder, EvmHandler }; use std::fmt::Debug; use std::vec::Vec; @@ -10,6 +7,9 @@ use std::vec::Vec; pub trait EvmWiring: PrimitiveEvmWiring { /// Creates a new handler with the given hardfork. fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self>; + + // Returns Revm Builder with + fn builder<'evm>() -> EvmBuilder<'evm,Self>; } impl EvmWiring for EthereumWiring { From 6528d3bb868943ace9379de77c8a63b41e7c033e Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 4 Sep 2024 14:50:36 +0200 Subject: [PATCH 46/59] wip --- crates/revm/src/builder.rs | 25 +++++++++++++++---------- crates/revm/src/chain_spec.rs | 8 ++++---- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 00d51f44f9..daa25eaf36 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -10,36 +10,39 @@ use std::boxed::Box; /// Evm Builder allows building or modifying EVM. /// Note that some of the methods that changes underlying structures /// will reset the registered handler to default mainnet. -pub struct EvmBuilder<'a, EvmWiringT: EvmWiring> { +pub struct EvmBuilder<'a, BuilderStage, EvmWiringT: EvmWiring> { database: Option, external_context: Option, env: Option>>, /// Handler that will be used by EVM. It contains handle registers handler: Handler<'a, EvmWiringT, Context>, + /// Phantom data to mark the stage of the builder. + phantom: PhantomData, } -// /// First stage of the builder allows setting generic variables. -// /// Generic variables are database and external context. -// pub struct SetGenericStage; +/// First stage of the builder allows setting generic variables. +/// Generic variables are database and external context. +pub struct SetGenericStage; -// /// Second stage of the builder allows appending handler registers. -// /// Requires the database and external context to be set. -// pub struct HandlerStage; +/// Second stage of the builder allows appending handler registers. +/// Requires the database and external context to be set. +pub struct HandlerStage; -impl<'a> Default for EvmBuilder<'a, EthereumWiring> { +impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring> { fn default() -> Self { Self::new() } } -impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, EvmWiringT> { +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { /// Sets the [`EvmWiring`] that will be used by [`Evm`]. - pub fn new() -> EvmBuilder<'a, EvmWiringT> { + pub fn new() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder { database: None, external_context: None, env: None, handler: EvmWiringT::handler::<'a>(EvmWiringT::Hardfork::default()), + phantom: PhantomData, } } @@ -54,6 +57,7 @@ impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, EvmWiringT> { external_context: Some(external_context), env: Some(env), handler, + phantom: PhantomData, } } @@ -65,6 +69,7 @@ impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, EvmWiringT> { external_context: None, env: None, handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), + phantom: PhantomData, } } diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/chain_spec.rs index baf2b53eb5..437dc71f40 100644 --- a/crates/revm/src/chain_spec.rs +++ b/crates/revm/src/chain_spec.rs @@ -1,5 +1,8 @@ use crate::{ - handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, interpreter::opcode::InstructionTables, primitives::{db::Database, spec_to_generic, EthereumWiring, EvmWiring as PrimitiveEvmWiring}, EvmBuilder, EvmHandler + handler::{ExecutionHandler, PostExecutionHandler, PreExecutionHandler, ValidationHandler}, + interpreter::opcode::InstructionTables, + primitives::{db::Database, spec_to_generic, EthereumWiring, EvmWiring as PrimitiveEvmWiring}, + EvmHandler, }; use std::fmt::Debug; use std::vec::Vec; @@ -7,9 +10,6 @@ use std::vec::Vec; pub trait EvmWiring: PrimitiveEvmWiring { /// Creates a new handler with the given hardfork. fn handler<'evm>(hardfork: Self::Hardfork) -> EvmHandler<'evm, Self>; - - // Returns Revm Builder with - fn builder<'evm>() -> EvmBuilder<'evm,Self>; } impl EvmWiring for EthereumWiring { From 0462c5b453dfcd3db1ab5794fd28902a7f6ca448 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 5 Sep 2024 14:35:56 +0200 Subject: [PATCH 47/59] fix compile --- crates/optimism/src/l1block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/optimism/src/l1block.rs b/crates/optimism/src/l1block.rs index 363625d654..9b33b0547d 100644 --- a/crates/optimism/src/l1block.rs +++ b/crates/optimism/src/l1block.rs @@ -443,7 +443,7 @@ mod tests { // test - let data_gas = l1_block_info.data_gas(TX, SpecId::FJORD); + let data_gas = l1_block_info.data_gas(TX, OptimismSpecId::FJORD); assert_eq!(data_gas, expected_data_gas); From c1c57ab0f2f13a394661bac141fc3c0cc19aeb02 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 5 Sep 2024 17:12:34 +0200 Subject: [PATCH 48/59] wip --- Cargo.lock | 1 + crates/optimism/Cargo.toml | 10 +- crates/optimism/src/bn128.rs | 5 +- crates/optimism/src/fast_lz.rs | 1 + crates/primitives/src/env/handler_cfg.rs | 159 ------------------ crates/revm/src/builder.rs | 19 ++- crates/revm/src/evm.rs | 7 +- crates/revm/src/inspector/handler_register.rs | 1 + 8 files changed, 35 insertions(+), 168 deletions(-) delete mode 100644 crates/primitives/src/env/handler_cfg.rs diff --git a/Cargo.lock b/Cargo.lock index 1b04d71256..68090593f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3149,6 +3149,7 @@ dependencies = [ "enumn", "indicatif", "revm", + "revm-precompile", "rstest", "serde", "serde_json", diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index 3a9e374743..e9937174ba 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -23,13 +23,19 @@ all = "warn" [dependencies] # revm -revm = { path = "../revm", version = "14.0.1", default-features = false, features=["std"] } +revm = { path = "../revm", version = "14.0.1", default-features = false, features = [ + "std", +] } +revm-precompile = { path = "../precompile", version = "11.0.1", default-features = false, features = [ + "std", + "secp256r1", +] } # misc auto_impl = { version = "1.2", default-features = false } derive-where = { version = "1.2.7", default-features = false } dyn-clone = "1.0" -enumn = { version = "0.1"} +enumn = { version = "0.1" } # Optional serde = { version = "1.0", default-features = false, features = [ diff --git a/crates/optimism/src/bn128.rs b/crates/optimism/src/bn128.rs index be5bee82fc..5603bef4bb 100644 --- a/crates/optimism/src/bn128.rs +++ b/crates/optimism/src/bn128.rs @@ -1,5 +1,6 @@ -use revm::precompile::bn128; -use revm::precompile::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use revm_precompile::{ + bn128, {Error, Precompile, PrecompileResult, PrecompileWithAddress}, +}; pub(crate) mod pair { use super::*; diff --git a/crates/optimism/src/fast_lz.rs b/crates/optimism/src/fast_lz.rs index 22e8188caa..a1498f4155 100644 --- a/crates/optimism/src/fast_lz.rs +++ b/crates/optimism/src/fast_lz.rs @@ -164,6 +164,7 @@ mod tests { let mut evm = Evm::>::builder() .with_db(BenchmarkDB::new_bytecode(contract_bytecode.clone())) + .with_default_ext_ctx() .modify_tx_env(|tx| { tx.base.caller = address!("1000000000000000000000000000000000000000"); tx.base.transact_to = diff --git a/crates/primitives/src/env/handler_cfg.rs b/crates/primitives/src/env/handler_cfg.rs deleted file mode 100644 index 56560ae675..0000000000 --- a/crates/primitives/src/env/handler_cfg.rs +++ /dev/null @@ -1,159 +0,0 @@ -use super::{BlockEnv, CfgEnv, Env, SpecId, TxEnv}; -use core::ops::{Deref, DerefMut}; -use std::boxed::Box; - -/// Handler configuration fields. It is used to configure the handler. -/// It contains specification id and the Optimism related field if -/// optimism feature is enabled. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub struct HandlerCfg { - /// Specification identification. - pub spec_id: SpecId, - /// Optimism related field, it will append the Optimism handle register to the EVM. - #[cfg(feature = "optimism")] - pub is_optimism: bool, -} - -impl Default for HandlerCfg { - fn default() -> Self { - Self::new(SpecId::default()) - } -} - -impl HandlerCfg { - /// Creates new `HandlerCfg` instance. - pub fn new(spec_id: SpecId) -> Self { - cfg_if::cfg_if! { - if #[cfg(all(feature = "optimism-default-handler", - not(feature = "negate-optimism-default-handler")))] { - let is_optimism = true; - } else if #[cfg(feature = "optimism")] { - let is_optimism = false; - } - } - Self { - spec_id, - #[cfg(feature = "optimism")] - is_optimism, - } - } - - /// Creates new `HandlerCfg` instance with the optimism feature. - #[cfg(feature = "optimism")] - pub fn new_with_optimism(spec_id: SpecId, is_optimism: bool) -> Self { - Self { - spec_id, - is_optimism, - } - } - - /// Returns `true` if the optimism feature is enabled and flag is set to `true`. - pub fn is_optimism(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optimism")] { - self.is_optimism - } else { - false - } - } - } -} - -/// Configuration environment with the chain spec id. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct CfgEnvWithHandlerCfg { - /// Configuration environment. - pub cfg_env: CfgEnv, - /// Handler configuration fields. - pub handler_cfg: HandlerCfg, -} - -impl CfgEnvWithHandlerCfg { - /// Returns new instance of `CfgEnvWithHandlerCfg` with the handler configuration. - pub fn new(cfg_env: CfgEnv, handler_cfg: HandlerCfg) -> Self { - Self { - cfg_env, - handler_cfg, - } - } - - /// Returns new `CfgEnvWithHandlerCfg` instance with the chain spec id. - /// - /// is_optimism will be set to default value depending on `optimism-default-handler` feature. - pub fn new_with_spec_id(cfg_env: CfgEnv, spec_id: SpecId) -> Self { - Self::new(cfg_env, HandlerCfg::new(spec_id)) - } - - /// Enables the optimism feature. - #[cfg(feature = "optimism")] - pub fn enable_optimism(&mut self) { - self.handler_cfg.is_optimism = true; - } -} - -impl DerefMut for CfgEnvWithHandlerCfg { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.cfg_env - } -} - -impl Deref for CfgEnvWithHandlerCfg { - type Target = CfgEnv; - - fn deref(&self) -> &Self::Target { - &self.cfg_env - } -} - -/// Evm environment with the chain spec id. -#[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct EnvWithHandlerCfg { - /// Evm environment. - pub env: Box, - /// Handler configuration fields. - pub handler_cfg: HandlerCfg, -} - -impl EnvWithHandlerCfg { - /// Returns new `EnvWithHandlerCfg` instance. - pub fn new(env: Box, handler_cfg: HandlerCfg) -> Self { - Self { env, handler_cfg } - } - - /// Returns new `EnvWithHandlerCfg` instance with the chain spec id. - /// - /// is_optimism will be set to default value depending on `optimism-default-handler` feature. - pub fn new_with_spec_id(env: Box, spec_id: SpecId) -> Self { - Self::new(env, HandlerCfg::new(spec_id)) - } - - /// Takes `CfgEnvWithHandlerCfg` and returns new `EnvWithHandlerCfg` instance. - pub fn new_with_cfg_env(cfg: CfgEnvWithHandlerCfg, block: BlockEnv, tx: TxEnv) -> Self { - Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.handler_cfg) - } - - /// Returns the specification id. - pub const fn spec_id(&self) -> SpecId { - self.handler_cfg.spec_id - } - - /// Enables the optimism handle register. - #[cfg(feature = "optimism")] - pub fn enable_optimism(&mut self) { - self.handler_cfg.is_optimism = true; - } -} - -impl DerefMut for EnvWithHandlerCfg { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.env - } -} - -impl Deref for EnvWithHandlerCfg { - type Target = Env; - - fn deref(&self) -> &Self::Target { - &self.env - } -} diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index daa25eaf36..818738ddc1 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -34,18 +34,24 @@ impl<'a> Default for EvmBuilder<'a, SetGenericStage, EthereumWiring } } -impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> +where + EvmWiringT::Transaction: Default, + EvmWiringT::Block: Default, +{ /// Sets the [`EvmWiring`] that will be used by [`Evm`]. pub fn new() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder { database: None, external_context: None, - env: None, + env: Some(Box::new(EnvWiring::::default())), handler: EvmWiringT::handler::<'a>(EvmWiringT::Hardfork::default()), phantom: PhantomData, } } +} +impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { pub fn new_with( database: EvmWiringT::Database, external_context: EvmWiringT::ExternalContext, @@ -63,11 +69,15 @@ impl<'a, EvmWiringT: EvmWiring> EvmBuilder<'a, SetGenericStage, EvmWiringT> { pub fn with_wiring( self, - ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> { + ) -> EvmBuilder<'a, SetGenericStage, NewEvmWiringT> + where + NewEvmWiringT::Transaction: Default, + NewEvmWiringT::Block: Default, + { EvmBuilder { database: None, external_context: None, - env: None, + env: Some(Box::new(EnvWiring::::default())), handler: NewEvmWiringT::handler::<'a>(NewEvmWiringT::Hardfork::default()), phantom: PhantomData, } @@ -476,6 +486,7 @@ mod test { let to_capture = custom_context.clone(); let mut evm = Evm::>::builder() .with_default_db() + .with_default_ext_ctx() .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index b5facbdb95..250809cec2 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -52,7 +52,11 @@ impl> Evm<'_, EvmWiringT> { } } -impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> { +impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> +where + EvmWiringT::Transaction: Default, + EvmWiringT::Block: Default, +{ /// Returns evm builder with the mainnet chain spec, empty database, and empty external context. pub fn builder() -> EvmBuilder<'a, SetGenericStage, EvmWiringT> { EvmBuilder::new() @@ -437,6 +441,7 @@ mod tests { let mut evm = Evm::>::builder() .with_spec_id(SpecId::PRAGUE) .with_db(BenchmarkDB::new_bytecode(bytecode)) + .with_default_ext_ctx() .modify_tx_env(|tx| { tx.authorization_list = Some( vec![RecoveredAuthorization::new_unchecked( diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index eef9875360..885d7d7d96 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -403,6 +403,7 @@ mod tests { fn test_inspector_reg() { let mut noop = NoOpInspector; let _evm: Evm<'_, EthereumWiring> = Evm::builder() + .with_default_db() .with_external_context(&mut noop) .append_handler_register(inspector_handle_register) .build(); From c4845c2d94ee5d55b29152e48414b05647f9010d Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 5 Sep 2024 17:18:22 +0200 Subject: [PATCH 49/59] fix optimism test --- crates/optimism/src/fast_lz.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/optimism/src/fast_lz.rs b/crates/optimism/src/fast_lz.rs index a1498f4155..327eb96f7b 100644 --- a/crates/optimism/src/fast_lz.rs +++ b/crates/optimism/src/fast_lz.rs @@ -106,12 +106,11 @@ fn u24(input: &[u8], idx: u32) -> u32 { #[cfg(test)] mod tests { use super::*; - use crate::OptimismEvmWiring; use alloy_sol_types::sol; use alloy_sol_types::SolCall; use revm::{ db::BenchmarkDB, - primitives::{address, bytes, Bytecode, Bytes, TxKind, U256}, + primitives::{address, bytes, Bytecode, Bytes, EthereumWiring, TxKind, U256}, Evm, }; @@ -162,14 +161,14 @@ mod tests { let native_val = flz_compress_len(&input); - let mut evm = Evm::>::builder() + let mut evm = Evm::>::builder() .with_db(BenchmarkDB::new_bytecode(contract_bytecode.clone())) .with_default_ext_ctx() .modify_tx_env(|tx| { - tx.base.caller = address!("1000000000000000000000000000000000000000"); - tx.base.transact_to = + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); - tx.base.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); + tx.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); }) .build(); From de4e89c0017986cac7323e732d97fd15e72af7ad Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 5 Sep 2024 19:21:37 +0200 Subject: [PATCH 50/59] fix docs ci --- .github/workflows/ci.yml | 6 ++++-- crates/optimism/src/fast_lz.rs | 3 +-- crates/revm/src/builder.rs | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3cb25136a..985ea7404a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,13 +38,15 @@ jobs: strategy: fail-fast: false matrix: - features: ["", "optimism,kzg-rs"] + features: ["", "kzg-rs"] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: targets: riscv32imac-unknown-none-elf - - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features --features=${{ matrix.features }} + - run: | + cargo check --target riscv32imac-unknown-none-elf --no-default-features --features=${{ matrix.features }} + cargo check --target riscv32imac-unknown-none-elf --p revm-optimism --no-default-features --features=${{ matrix.features }} check: name: check ${{ matrix.features }} diff --git a/crates/optimism/src/fast_lz.rs b/crates/optimism/src/fast_lz.rs index 327eb96f7b..f931697cb1 100644 --- a/crates/optimism/src/fast_lz.rs +++ b/crates/optimism/src/fast_lz.rs @@ -166,8 +166,7 @@ mod tests { .with_default_ext_ctx() .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = - TxKind::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); }) .build(); diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 818738ddc1..f1c4b6a31d 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -289,10 +289,10 @@ impl<'a, BuilderStage, EvmWiringT: EvmWiring> EvmBuilder<'a, BuilderStage, EvmWi /// ```rust /// use revm::{EvmBuilder, EvmHandler, db::EmptyDB, primitives::{EthereumWiring, SpecId}}; /// use revm_interpreter::primitives::CancunSpec; - /// let builder = EvmBuilder::default(); + /// let builder = EvmBuilder::default().with_default_db().with_default_ext_ctx(); /// /// // get the desired handler - /// let mainnet = EvmHandler::<'_, EthereumWiring, (), EmptyDB>::mainnet_with_spec(SpecId::CANCUN); + /// let mainnet = EvmHandler::<'_, EthereumWiring>::mainnet_with_spec(SpecId::CANCUN); /// let builder = builder.with_handler(mainnet); /// /// // build the EVM From 492c27a2626160eff33cf6c4ac34d20f5391b137 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 02:08:26 +0200 Subject: [PATCH 51/59] cleanup --- crates/interpreter/Cargo.toml | 4 - crates/optimism/Cargo.toml | 2 - crates/precompile/Cargo.toml | 2 - crates/primitives/Cargo.toml | 4 - crates/primitives/src/env.rs | 18 +--- crates/primitives/src/result.rs | 5 + crates/revm/Cargo.toml | 7 -- crates/revm/src/evm.rs | 28 +++--- .../revm/src/{chain_spec.rs => evm_wiring.rs} | 0 crates/revm/src/handler.rs | 2 - crates/revm/src/handler/cfg.rs | 94 ------------------- .../src/handler/handle_types/pre_execution.rs | 2 +- crates/revm/src/handler/mainnet/execution.rs | 2 +- crates/revm/src/lib.rs | 4 +- 14 files changed, 30 insertions(+), 144 deletions(-) rename crates/revm/src/{chain_spec.rs => evm_wiring.rs} (100%) delete mode 100644 crates/revm/src/handler/cfg.rs diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 22c7393c1d..114c89c415 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -51,8 +51,6 @@ asm-keccak = ["revm-primitives/asm-keccak"] portable = ["revm-primitives/portable"] parse = ["dep:paste", "dep:phf"] -optimism = ["revm-primitives/optimism"] - dev = [ "memory_limit", "optional_balance_check", @@ -61,7 +59,6 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", - "optional_nonce_check", ] memory_limit = ["revm-primitives/memory_limit"] optional_balance_check = ["revm-primitives/optional_balance_check"] @@ -70,6 +67,5 @@ optional_eip3607 = ["revm-primitives/optional_eip3607"] optional_gas_refund = ["revm-primitives/optional_gas_refund"] optional_no_base_fee = ["revm-primitives/optional_no_base_fee"] optional_beneficiary_reward = ["revm-primitives/optional_beneficiary_reward"] -optional_nonce_check = ["revm-primitives/optional_nonce_check"] kzg-rs = ["revm-primitives/kzg-rs"] diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index e9937174ba..bada601f5d 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -78,7 +78,6 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", - "optional_nonce_check", ] memory_limit = ["revm/memory_limit"] optional_balance_check = ["revm/optional_balance_check"] @@ -87,7 +86,6 @@ optional_eip3607 = ["revm/optional_eip3607"] optional_gas_refund = ["revm/optional_gas_refund"] optional_no_base_fee = ["revm/optional_no_base_fee"] optional_beneficiary_reward = ["revm/optional_beneficiary_reward"] -optional_nonce_check = ["revm/optional_nonce_check"] # See comments in `revm-precompile` secp256k1 = ["revm/secp256k1"] diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 6eaeff3398..04cb1104eb 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -86,8 +86,6 @@ std = [ hashbrown = ["revm-primitives/hashbrown"] asm-keccak = ["revm-primitives/asm-keccak"] -optimism = ["revm-primitives/optimism", "secp256r1"] - # Enables the p256verify precompile. secp256r1 = ["dep:p256"] diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index b5378a2916..a02ba81fa3 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -83,8 +83,6 @@ arbitrary = [ asm-keccak = ["alloy-primitives/asm-keccak"] portable = ["c-kzg?/portable"] -optimism = [] - dev = [ "memory_limit", "optional_balance_check", @@ -93,7 +91,6 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", - "optional_nonce_check", ] memory_limit = [] optional_balance_check = [] @@ -102,7 +99,6 @@ optional_eip3607 = [] optional_gas_refund = [] optional_no_base_fee = [] optional_beneficiary_reward = [] -optional_nonce_check = [] rand = ["alloy-primitives/rand"] # See comments in `revm-precompile` diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 6c42e67878..7e48b175de 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -307,6 +307,10 @@ pub struct CfgEnv { /// If some it will effects EIP-170: Contract code size limit. Useful to increase this because of tests. /// By default it is 0x6000 (~25kb). pub limit_contract_code_size: Option, + /// Skips the nonce validation against the account's nonce: + /// [`crate::InvalidTransaction::NonceTooHigh`] and + /// [`crate::InvalidTransaction::NonceTooLow`] + pub disable_nonce_check: bool, /// A hard memory limit in bytes beyond which [crate::result::OutOfGasError::Memory] cannot be resized. /// /// In cases where the gas limit may be extraordinarily high, it is recommended to set this to @@ -341,11 +345,6 @@ pub struct CfgEnv { /// By default, it is set to `false`. #[cfg(feature = "optional_beneficiary_reward")] pub disable_beneficiary_reward: bool, - /// Skips the nonce validation against the account's nonce: - /// [`crate::InvalidTransaction::NonceTooHigh`] and - /// [`crate::InvalidTransaction::NonceTooLow`] - #[cfg(feature = "optional_nonce_check")] - pub disable_nonce_check: bool, } impl CfgEnv { @@ -420,15 +419,9 @@ impl CfgEnv { false } - #[cfg(feature = "optional_nonce_check")] pub const fn is_nonce_check_disabled(&self) -> bool { self.disable_nonce_check } - - #[cfg(not(feature = "optional_nonce_check"))] - pub const fn is_nonce_check_disabled(&self) -> bool { - false - } } impl Default for CfgEnv { @@ -437,6 +430,7 @@ impl Default for CfgEnv { chain_id: 1, perf_analyse_created_bytecodes: AnalysisKind::default(), limit_contract_code_size: None, + disable_nonce_check: false, #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] kzg_settings: crate::kzg::EnvKzgSettings::Default, #[cfg(feature = "memory_limit")] @@ -453,8 +447,6 @@ impl Default for CfgEnv { disable_base_fee: false, #[cfg(feature = "optional_beneficiary_reward")] disable_beneficiary_reward: false, - #[cfg(feature = "optional_nonce_check")] - disable_nonce_check: false, } } } diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index a8d448af97..8596991292 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -144,6 +144,11 @@ impl Output { } } +pub type EVMErrorWiring = EVMError< + <::Database as Database>::Error, + <::Transaction as TransactionValidation>::ValidationError, +>; + /// Main EVM error. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 49b70d977b..9c3686c50d 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -102,7 +102,6 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", "optional_beneficiary_reward", - "optional_nonce_check", ] memory_limit = ["revm-interpreter/memory_limit"] optional_balance_check = ["revm-interpreter/optional_balance_check"] @@ -111,7 +110,6 @@ optional_eip3607 = ["revm-interpreter/optional_eip3607"] optional_gas_refund = ["revm-interpreter/optional_gas_refund"] optional_no_base_fee = ["revm-interpreter/optional_no_base_fee"] optional_beneficiary_reward = ["revm-interpreter/optional_beneficiary_reward"] -optional_nonce_check = ["revm-interpreter/optional_nonce_check"] # See comments in `revm-precompile` secp256k1 = ["revm-precompile/secp256k1"] @@ -140,11 +138,6 @@ required-features = ["std", "serde-json"] #path = "../../examples/uniswap_v2_usdc_swap.rs" #required-features = ["alloydb"] -#[[example]] -#name = "custom_opcodes" -#path = "../../examples/custom_opcodes.rs" -#required-features = [] - [[bench]] name = "bench" path = "benches/bench.rs" diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 250809cec2..82a0beed6d 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -3,11 +3,11 @@ use revm_interpreter::Host as _; use crate::{ builder::{EvmBuilder, SetGenericStage}, db::{Database, DatabaseCommit}, - handler::{EnvWithEvmWiring, Handler}, + handler::Handler, interpreter::{CallInputs, CreateInputs, EOFCreateInputs, InterpreterAction, SharedMemory}, primitives::{ - CfgEnv, EVMError, EVMResult, EVMResultGeneric, ExecutionResult, ResultAndState, SpecId, - Transaction, TxKind, EOF_MAGIC_BYTES, + CfgEnv, EVMError, EVMResult, EVMResultGeneric, EnvWiring, ExecutionResult, ResultAndState, + SpecId, Transaction, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithEvmWiring, EvmContext, EvmWiring, Frame, FrameOrResult, FrameResult, InnerEvmContext, @@ -91,10 +91,6 @@ impl<'a, EvmWiringT: EvmWiring> Evm<'a, EvmWiringT> { }, handler, } = self; - // let handler = self.handler; - // let db = self.context.evm.db; - // let ext = self.context.external; - // let env = self.context.evm.env; EvmBuilder::<'a>::new_with(db, external, env, handler) } @@ -316,6 +312,12 @@ impl Evm<'_, EvmWiringT> { &mut self.context.evm.env.block } + /// Modify spec id, this will create new EVM that matches this spec id. + pub fn modify_spec_id(&mut self, spec_id: EvmWiringT::Hardfork) { + self.context.evm.journaled_state.set_spec_id(spec_id.into()); + self.handler.modify_spec_id(spec_id); + } + /// Returns internal database and external struct. #[inline] pub fn into_context(self) -> Context { @@ -326,13 +328,15 @@ impl Evm<'_, EvmWiringT> { #[inline] pub fn into_db_and_env_with_handler_cfg( self, - ) -> (EvmWiringT::Database, EnvWithEvmWiring) { + ) -> ( + EvmWiringT::Database, + Box>, + EvmWiringT::Hardfork, + ) { ( self.context.evm.inner.db, - EnvWithEvmWiring { - env: self.context.evm.inner.env, - spec_id: self.handler.spec_id, - }, + self.context.evm.inner.env, + self.handler.spec_id, ) } diff --git a/crates/revm/src/chain_spec.rs b/crates/revm/src/evm_wiring.rs similarity index 100% rename from crates/revm/src/chain_spec.rs rename to crates/revm/src/evm_wiring.rs diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index 02aba1de22..ade4292a53 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -1,11 +1,9 @@ // Modules. -pub mod cfg; mod handle_types; pub mod mainnet; pub mod register; // Exports. -pub use cfg::{CfgEnvWithEvmWiring, EnvWithEvmWiring}; pub use handle_types::*; // Includes. diff --git a/crates/revm/src/handler/cfg.rs b/crates/revm/src/handler/cfg.rs deleted file mode 100644 index bcd4040917..0000000000 --- a/crates/revm/src/handler/cfg.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::primitives::{CfgEnv, Env, EnvWiring, EvmWiring}; -use core::{ - fmt::Debug, - ops::{Deref, DerefMut}, -}; -use derive_where::derive_where; -use std::boxed::Box; - -/// Configuration environment with the chain spec id. -#[derive(Debug, Eq, PartialEq)] -#[derive_where(Clone; EvmWiringT::Hardfork)] -pub struct CfgEnvWithEvmWiring { - /// Configuration environment. - pub cfg_env: CfgEnv, - /// Handler configuration fields. - pub spec_id: EvmWiringT::Hardfork, -} - -impl CfgEnvWithEvmWiring { - /// Returns new instance of `CfgEnvWithHandlerCfg`. - pub fn new(cfg_env: CfgEnv, spec_id: EvmWiringT::Hardfork) -> Self { - Self { cfg_env, spec_id } - } -} - -impl DerefMut for CfgEnvWithEvmWiring { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.cfg_env - } -} - -impl Deref for CfgEnvWithEvmWiring { - type Target = CfgEnv; - - fn deref(&self) -> &Self::Target { - &self.cfg_env - } -} - -/// Evm environment with the chain spec id. -#[derive_where(Clone, Debug; EvmWiringT::Block, EvmWiringT::Hardfork, EvmWiringT::Transaction)] -pub struct EnvWithEvmWiring -where - EvmWiringT: EvmWiring, -{ - /// Evm enironment. - pub env: Box>, - /// Handler configuration fields. - pub spec_id: EvmWiringT::Hardfork, -} - -impl EnvWithEvmWiring -where - EvmWiringT: EvmWiring, -{ - /// Returns new `EnvWithHandlerCfg` instance. - pub fn new(env: Box>, spec_id: EvmWiringT::Hardfork) -> Self { - Self { env, spec_id } - } - - /// Takes `CfgEnvWithHandlerCfg` and returns new `EnvWithHandlerCfg` instance. - pub fn new_with_cfg_env( - cfg: CfgEnvWithEvmWiring, - block: EvmWiringT::Block, - tx: EvmWiringT::Transaction, - ) -> Self { - Self::new(Env::boxed(cfg.cfg_env, block, tx), cfg.spec_id) - } - - /// Returns the specification id. - pub const fn spec_id(&self) -> EvmWiringT::Hardfork { - self.spec_id - } -} - -impl DerefMut for EnvWithEvmWiring -where - EvmWiringT: EvmWiring, -{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.env - } -} - -impl Deref for EnvWithEvmWiring -where - EvmWiringT: EvmWiring, -{ - type Target = EnvWiring; - - fn deref(&self) -> &Self::Target { - &self.env - } -} diff --git a/crates/revm/src/handler/handle_types/pre_execution.rs b/crates/revm/src/handler/handle_types/pre_execution.rs index 486f90a620..7a4f3a2474 100644 --- a/crates/revm/src/handler/handle_types/pre_execution.rs +++ b/crates/revm/src/handler/handle_types/pre_execution.rs @@ -26,7 +26,7 @@ pub type ApplyEIP7702AuthListHandle<'a, EvmWiringT> = GenericContextHandleRet<'a pub struct PreExecutionHandler<'a, EvmWiringT: EvmWiring> { /// Load precompiles pub load_precompiles: LoadPrecompilesHandle<'a, EvmWiringT>, - // /// Main load handle + /// Main load handle pub load_accounts: LoadAccountsHandle<'a, EvmWiringT>, /// Deduct max value from the caller. pub deduct_caller: DeductCallerHandle<'a, EvmWiringT>, diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index d7b11f1a65..0c5bb0ecf0 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -180,7 +180,7 @@ pub fn insert_eofcreate_outcome( frame: &mut Frame, outcome: CreateOutcome, ) -> EVMResultGeneric<(), EvmWiringT> { - core::mem::replace(&mut context.evm.error, Ok(())).map_err(EVMError::Database)?; + context.evm.take_error().map_err(EVMError::Database)?; frame .frame_data_mut() diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index fc1ffd0a01..33f77cff9d 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -14,9 +14,9 @@ mod context; #[cfg(any(test, feature = "test-utils"))] pub mod test_utils; -mod chain_spec; pub mod db; mod evm; +mod evm_wiring; mod frame; pub mod handler; mod inspector; @@ -25,7 +25,6 @@ mod journaled_state; // Export items. pub use builder::EvmBuilder; -pub use chain_spec::EvmWiring; pub use context::{ Context, ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc, ContextStatefulPrecompileBox, ContextStatefulPrecompileMut, @@ -36,6 +35,7 @@ pub use db::{ }; pub use db::{Database, DatabaseCommit, DatabaseRef, InMemoryDB}; pub use evm::{Evm, CALL_STACK_LIMIT}; +pub use evm_wiring::EvmWiring; pub use frame::{CallFrame, CreateFrame, Frame, FrameData, FrameOrResult, FrameResult}; pub use handler::{register::EvmHandler, Handler}; pub use inspector::{inspector_handle_register, inspectors, GetInspector, Inspector}; From f1faa4746c29250cb85c50bfc2c6a382473ded46 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 03:19:19 +0200 Subject: [PATCH 52/59] cleanup --- .github/workflows/ci.yml | 2 +- Cargo.lock | 3 --- Cargo.toml | 2 +- crates/interpreter/src/function_stack.rs | 3 +-- crates/interpreter/src/interpreter/contract.rs | 2 +- crates/optimism/Cargo.toml | 12 +++--------- crates/optimism/src/bn128.rs | 2 +- crates/optimism/src/fast_lz.rs | 1 + crates/optimism/src/handler_register.rs | 6 +++--- crates/optimism/src/lib.rs | 5 +++++ crates/optimism/src/result.rs | 1 - crates/primitives/src/evm_wiring.rs | 5 +---- crates/revm/src/context/context_precompiles.rs | 2 +- crates/revm/src/handler.rs | 2 +- 14 files changed, 20 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 985ea7404a..be78248b81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: targets: riscv32imac-unknown-none-elf - run: | cargo check --target riscv32imac-unknown-none-elf --no-default-features --features=${{ matrix.features }} - cargo check --target riscv32imac-unknown-none-elf --p revm-optimism --no-default-features --features=${{ matrix.features }} + cargo check --target riscv32imac-unknown-none-elf -p revm-optimism --no-default-features --features=${{ matrix.features }} check: name: check ${{ matrix.features }} diff --git a/Cargo.lock b/Cargo.lock index 68090593f2..661b5e662e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3142,10 +3142,7 @@ dependencies = [ "alloy-provider", "alloy-sol-types", "anyhow", - "auto_impl", "criterion", - "derive-where", - "dyn-clone", "enumn", "indicatif", "revm", diff --git a/Cargo.toml b/Cargo.toml index 48b6ffe24b..12d19a5568 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [profile.release] -#lto = true +lto = true codegen-units = 1 debug = true diff --git a/crates/interpreter/src/function_stack.rs b/crates/interpreter/src/function_stack.rs index 4c33aa911c..3363577266 100644 --- a/crates/interpreter/src/function_stack.rs +++ b/crates/interpreter/src/function_stack.rs @@ -51,9 +51,8 @@ impl FunctionStack { /// Pops a frame from the stack and sets current_code_idx to the popped frame's idx. pub fn pop(&mut self) -> Option { - self.return_stack.pop().map(|frame| { + self.return_stack.pop().inspect(|frame| { self.current_code_idx = frame.idx; - frame }) } diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 9a0db41152..5dc50f4d0d 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -53,7 +53,7 @@ impl Contract { } } - /// Creates a new contract from the given [`Env`]. + /// Creates a new contract from the given [`EnvWiring`]. #[inline] pub fn new_env( env: &EnvWiring, diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index bada601f5d..d810f152cc 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -23,18 +23,12 @@ all = "warn" [dependencies] # revm -revm = { path = "../revm", version = "14.0.1", default-features = false, features = [ - "std", -] } +revm = { path = "../revm", version = "14.0.1", default-features = false } revm-precompile = { path = "../precompile", version = "11.0.1", default-features = false, features = [ - "std", "secp256r1", ] } # misc -auto_impl = { version = "1.2", default-features = false } -derive-where = { version = "1.2.7", default-features = false } -dyn-clone = "1.0" enumn = { version = "0.1" } # Optional @@ -63,13 +57,13 @@ std = [ "serde_json?/std", "serde_json?/preserve_order", "revm/std", + "revm-precompile/std", ] hashbrown = ["revm/hashbrown"] serde = ["dep:serde", "revm/serde"] -serde-json = ["serde", "dep:serde_json"] +serde-json = ["serde", "dep:serde_json", "revm/serde-json"] portable = ["revm/portable"] - dev = [ "memory_limit", "optional_balance_check", diff --git a/crates/optimism/src/bn128.rs b/crates/optimism/src/bn128.rs index 5603bef4bb..89ad4d4731 100644 --- a/crates/optimism/src/bn128.rs +++ b/crates/optimism/src/bn128.rs @@ -27,7 +27,7 @@ pub(crate) mod pair { #[cfg(test)] mod tests { use revm::primitives::{hex, PrecompileErrors}; - + use std::vec; use super::*; #[test] diff --git a/crates/optimism/src/fast_lz.rs b/crates/optimism/src/fast_lz.rs index f931697cb1..cdcaff5849 100644 --- a/crates/optimism/src/fast_lz.rs +++ b/crates/optimism/src/fast_lz.rs @@ -113,6 +113,7 @@ mod tests { primitives::{address, bytes, Bytecode, Bytes, EthereumWiring, TxKind, U256}, Evm, }; + use std::vec::Vec; use rstest::rstest; diff --git a/crates/optimism/src/handler_register.rs b/crates/optimism/src/handler_register.rs index bdcc16a2ce..800ea1a210 100644 --- a/crates/optimism/src/handler_register.rs +++ b/crates/optimism/src/handler_register.rs @@ -19,7 +19,6 @@ use revm::{ }, Context, ContextPrecompiles, FrameResult, }; -use std::string::ToString; use std::sync::Arc; pub fn optimism_handle_register(handler: &mut EvmHandler<'_, EvmWiringT>) @@ -246,7 +245,7 @@ pub fn deduct_caller( // get envelope let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx() else { return Err(EVMError::Custom( - "[OPTIMISM] Failed to load enveloped transaction.".to_string(), + "[OPTIMISM] Failed to load enveloped transaction.".into(), )); }; @@ -295,7 +294,7 @@ pub fn reward_beneficiary( let Some(enveloped_tx) = &context.evm.inner.env.tx.enveloped_tx() else { return Err(EVMError::Custom( - "[OPTIMISM] Failed to load enveloped transaction.".to_string(), + "[OPTIMISM] Failed to load enveloped transaction.".into(), )); }; @@ -428,6 +427,7 @@ mod tests { interpreter::{CallOutcome, InterpreterResult}, primitives::{bytes, state::AccountInfo, Address, Bytes, B256}, }; + use std::boxed::Box; type TestEmptyOpWiring = OptimismEvmWiring; type TestMemOpWiring = OptimismEvmWiring; diff --git a/crates/optimism/src/lib.rs b/crates/optimism/src/lib.rs index 03a4572eaf..c53a2a25db 100644 --- a/crates/optimism/src/lib.rs +++ b/crates/optimism/src/lib.rs @@ -1,4 +1,9 @@ //! Optimism-specific constants, types, and helpers. +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc as std; mod bn128; mod env; diff --git a/crates/optimism/src/result.rs b/crates/optimism/src/result.rs index 9b5227669e..2749f91581 100644 --- a/crates/optimism/src/result.rs +++ b/crates/optimism/src/result.rs @@ -1,5 +1,4 @@ use core::fmt::Display; - use revm::primitives::{EVMError, HaltReason, InvalidTransaction}; /// Optimism transaction validation error. diff --git a/crates/primitives/src/evm_wiring.rs b/crates/primitives/src/evm_wiring.rs index 88adb7ea68..1abf790377 100644 --- a/crates/primitives/src/evm_wiring.rs +++ b/crates/primitives/src/evm_wiring.rs @@ -1,7 +1,4 @@ -use cfg_if::cfg_if; - use crate::{db::Database, Block, SpecId, Transaction}; - use core::{fmt::Debug, hash::Hash}; /// The type that enumerates the chain's hardforks. @@ -20,7 +17,7 @@ impl HaltReasonTrait for HaltReasonT where } pub trait TransactionValidation { - cfg_if! { + cfg_if::cfg_if! { if #[cfg(feature = "std")] { /// An error that occurs when validating a transaction. type ValidationError: Debug + std::error::Error; diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index c3a1978d69..2b1c141214 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -84,7 +84,7 @@ impl ContextPrecompiles { /// Returns precompiles addresses. #[inline] - pub fn addresses<'a>(&'a self) -> Box + 'a> { + pub fn addresses(&self) -> Box + '_> { match self.inner { PrecompilesCow::StaticRef(inner) => Box::new(inner.addresses()), PrecompilesCow::Owned(ref inner) => Box::new(inner.keys()), diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index ade4292a53..042c3e6108 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -184,7 +184,7 @@ mod test { let inner = inner.clone(); Box::new(move |h| { *inner.borrow_mut() += 1; - h.post_execution.output = Arc::new(|_, _| Err(EVMError::Custom("test".to_string()))) + h.post_execution.output = Arc::new(|_, _| Err(EVMError::Custom("test".into()))) }) }; From f97ce4735685799f76d84c00dd19278cef899393 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 03:27:54 +0200 Subject: [PATCH 53/59] use core::error::Error --- crates/interpreter/src/interpreter/analysis.rs | 6 ++---- crates/interpreter/src/opcode.rs | 4 ++-- crates/optimism/src/result.rs | 3 +-- crates/primitives/src/bytecode.rs | 3 +-- crates/primitives/src/bytecode/eof.rs | 3 +-- crates/primitives/src/eip7702/bytecode.rs | 3 +-- crates/primitives/src/precompile.rs | 6 ++---- crates/primitives/src/result.rs | 6 ++---- 8 files changed, 12 insertions(+), 22 deletions(-) diff --git a/crates/interpreter/src/interpreter/analysis.rs b/crates/interpreter/src/interpreter/analysis.rs index 0f3651a7bd..c2ea93506c 100644 --- a/crates/interpreter/src/interpreter/analysis.rs +++ b/crates/interpreter/src/interpreter/analysis.rs @@ -219,8 +219,7 @@ impl fmt::Display for EofError { } } -#[cfg(feature = "std")] -impl std::error::Error for EofError {} +impl core::error::Error for EofError {} #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub enum EofValidationError { @@ -442,8 +441,7 @@ impl fmt::Display for EofValidationError { } } -#[cfg(feature = "std")] -impl std::error::Error for EofValidationError {} +impl core::error::Error for EofValidationError {} /// Validates that: /// * All instructions are valid. diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index 7de81588e4..587810f5d6 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -24,8 +24,8 @@ impl fmt::Display for OpCodeError { } } -#[cfg(all(feature = "std", feature = "parse"))] -impl std::error::Error for OpCodeError {} +#[cfg(feature = "parse")] +impl core::error::Error for OpCodeError {} /// An EVM opcode. /// diff --git a/crates/optimism/src/result.rs b/crates/optimism/src/result.rs index 2749f91581..63093fc9f5 100644 --- a/crates/optimism/src/result.rs +++ b/crates/optimism/src/result.rs @@ -58,8 +58,7 @@ impl Display for OptimismInvalidTransaction { } } -#[cfg(feature = "std")] -impl std::error::Error for OptimismInvalidTransaction {} +impl core::error::Error for OptimismInvalidTransaction {} impl From for OptimismInvalidTransaction { fn from(value: InvalidTransaction) -> Self { diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index bae4161806..d3fbbd2868 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -235,8 +235,7 @@ impl From for BytecodeDecodeError { } } -#[cfg(feature = "std")] -impl std::error::Error for BytecodeDecodeError {} +impl core::error::Error for BytecodeDecodeError {} impl fmt::Display for BytecodeDecodeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/crates/primitives/src/bytecode/eof.rs b/crates/primitives/src/bytecode/eof.rs index 8ed12abb86..d25f61f6d9 100644 --- a/crates/primitives/src/bytecode/eof.rs +++ b/crates/primitives/src/bytecode/eof.rs @@ -182,8 +182,7 @@ impl fmt::Display for EofDecodeError { } } -#[cfg(feature = "std")] -impl std::error::Error for EofDecodeError {} +impl core::error::Error for EofDecodeError {} #[cfg(test)] mod test { diff --git a/crates/primitives/src/eip7702/bytecode.rs b/crates/primitives/src/eip7702/bytecode.rs index 268f2c4aa6..89a8082389 100644 --- a/crates/primitives/src/eip7702/bytecode.rs +++ b/crates/primitives/src/eip7702/bytecode.rs @@ -93,8 +93,7 @@ impl fmt::Display for Eip7702DecodeError { } } -#[cfg(feature = "std")] -impl std::error::Error for Eip7702DecodeError {} +impl core::error::Error for Eip7702DecodeError {} #[cfg(test)] mod tests { diff --git a/crates/primitives/src/precompile.rs b/crates/primitives/src/precompile.rs index 890e1b537e..25938bb580 100644 --- a/crates/primitives/src/precompile.rs +++ b/crates/primitives/src/precompile.rs @@ -140,8 +140,7 @@ pub enum PrecompileErrors { Fatal { msg: String }, } -#[cfg(feature = "std")] -impl std::error::Error for PrecompileErrors {} +impl core::error::Error for PrecompileErrors {} impl fmt::Display for PrecompileErrors { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -196,8 +195,7 @@ impl From for PrecompileErrors { } } -#[cfg(feature = "std")] -impl std::error::Error for PrecompileError {} +impl core::error::Error for PrecompileError {} impl fmt::Display for PrecompileError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 8596991292..7dee33d49d 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -311,8 +311,7 @@ impl From for InvalidTransaction { } } -#[cfg(feature = "std")] -impl std::error::Error for InvalidTransaction {} +impl core::error::Error for InvalidTransaction {} impl fmt::Display for InvalidTransaction { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -388,8 +387,7 @@ pub enum InvalidHeader { ExcessBlobGasNotSet, } -#[cfg(feature = "std")] -impl std::error::Error for InvalidHeader {} +impl core::error::Error for InvalidHeader {} impl fmt::Display for InvalidHeader { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { From d64f6245c9eee4291ff03cc9f85526f384e733f0 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 03:31:39 +0200 Subject: [PATCH 54/59] cleanup --- Cargo.lock | 1 - crates/optimism/Cargo.toml | 7 +------ crates/optimism/src/bn128.rs | 2 +- crates/primitives/src/evm_wiring.rs | 11 ++--------- crates/revm/src/evm.rs | 6 ++---- 5 files changed, 6 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 661b5e662e..12ebe50ecb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3149,7 +3149,6 @@ dependencies = [ "revm-precompile", "rstest", "serde", - "serde_json", ] [[package]] diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index d810f152cc..ca3fdd2ce6 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -36,9 +36,6 @@ serde = { version = "1.0", default-features = false, features = [ "derive", "rc", ], optional = true } -serde_json = { version = "1.0", default-features = false, features = [ - "alloc", -], optional = true } [dev-dependencies] @@ -54,14 +51,12 @@ alloy-provider = "0.3" default = ["std", "c-kzg", "secp256k1", "portable", "blst"] std = [ "serde?/std", - "serde_json?/std", - "serde_json?/preserve_order", "revm/std", "revm-precompile/std", ] hashbrown = ["revm/hashbrown"] serde = ["dep:serde", "revm/serde"] -serde-json = ["serde", "dep:serde_json", "revm/serde-json"] +serde-json = ["serde", "revm/serde-json"] portable = ["revm/portable"] dev = [ diff --git a/crates/optimism/src/bn128.rs b/crates/optimism/src/bn128.rs index 89ad4d4731..b61be4ac34 100644 --- a/crates/optimism/src/bn128.rs +++ b/crates/optimism/src/bn128.rs @@ -26,9 +26,9 @@ pub(crate) mod pair { #[cfg(test)] mod tests { + use super::*; use revm::primitives::{hex, PrecompileErrors}; use std::vec; - use super::*; #[test] fn test_bn128_pair() { diff --git a/crates/primitives/src/evm_wiring.rs b/crates/primitives/src/evm_wiring.rs index 1abf790377..6c1c44b23e 100644 --- a/crates/primitives/src/evm_wiring.rs +++ b/crates/primitives/src/evm_wiring.rs @@ -17,15 +17,8 @@ impl HaltReasonTrait for HaltReasonT where } pub trait TransactionValidation { - cfg_if::cfg_if! { - if #[cfg(feature = "std")] { - /// An error that occurs when validating a transaction. - type ValidationError: Debug + std::error::Error; - } else { - /// An error that occurs when validating a transaction. - type ValidationError: Debug; - } - } + /// An error that occurs when validating a transaction. + type ValidationError: Debug + std::error::Error; } pub trait EvmWiring: Sized { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 82a0beed6d..926ae2ab63 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -224,9 +224,8 @@ impl Evm<'_, EvmWiringT> { .handler .validation() .initial_tx_gas(&self.context.evm.env) - .map_err(|e| { + .inspect_err(|_| { self.clear(); - e })?; let output = self.transact_preverified_inner(initial_gas_spend); let output = self.handler.post_execution().end(&mut self.context, output); @@ -253,9 +252,8 @@ impl Evm<'_, EvmWiringT> { /// This function will validate the transaction. #[inline] pub fn transact(&mut self) -> EVMResult { - let initial_gas_spend = self.preverify_transaction_inner().map_err(|e| { + let initial_gas_spend = self.preverify_transaction_inner().inspect_err(|_| { self.clear(); - e })?; let output = self.transact_preverified_inner(initial_gas_spend); From 4a7e6e3369aee77784172a7501b1e73828209afe Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 11:35:15 +0200 Subject: [PATCH 55/59] use core error --- crates/primitives/src/evm_wiring.rs | 2 +- examples/db_by_ref.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/primitives/src/evm_wiring.rs b/crates/primitives/src/evm_wiring.rs index 6c1c44b23e..12ae764301 100644 --- a/crates/primitives/src/evm_wiring.rs +++ b/crates/primitives/src/evm_wiring.rs @@ -18,7 +18,7 @@ impl HaltReasonTrait for HaltReasonT where pub trait TransactionValidation { /// An error that occurs when validating a transaction. - type ValidationError: Debug + std::error::Error; + type ValidationError: Debug + core::error::Error; } pub trait EvmWiring: Sized { diff --git a/examples/db_by_ref.rs b/examples/db_by_ref.rs index 14c5b32d3b..4801db5a1b 100644 --- a/examples/db_by_ref.rs +++ b/examples/db_by_ref.rs @@ -1,3 +1,4 @@ +use core::error::Error; use core::fmt::Debug; use revm::{ db::{CacheDB, EmptyDB, WrapDatabaseRef}, @@ -7,7 +8,6 @@ use revm::{ primitives::{EthereumWiring, HaltReason, ResultAndState}, DatabaseCommit, DatabaseRef, Evm, }; -use std::error::Error; trait DatabaseRefDebugError: DatabaseRef { type DBError: std::fmt::Debug + Error + Send + Sync + 'static; From d51cc59563b35f9d3ba18c28450069b95d721098 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 11:48:44 +0200 Subject: [PATCH 56/59] fix builer --- bins/revme/src/cmd/statetest/runner.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 3e0f172753..b3e01f3392 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -391,6 +391,7 @@ pub fn execute_test_suite( .build(); let mut evm = Evm::::builder() .with_db(&mut state) + .with_default_ext_ctx() .modify_env(|e| e.clone_from(&env)) .with_spec_id(spec_id) .build(); From e7d78ca422b6031e071c7ee3f7c9930cab4911e6 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 11:55:14 +0200 Subject: [PATCH 57/59] fix docs --- crates/revm/src/builder.rs | 2 +- crates/revm/src/evm.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index f1c4b6a31d..49ae0e31ab 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -148,7 +148,7 @@ where self } - /// Sets the [`Database`] that will be used by [`Evm`]. + /// Sets the [`crate::Database`] that will be used by [`Evm`]. pub fn with_db( mut self, db: EvmWiringT::Database, diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 926ae2ab63..f674018f73 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -322,7 +322,7 @@ impl Evm<'_, EvmWiringT> { self.context } - /// Returns database and [`EnvWithEvmWiring`]. + /// Returns database, [`EnvWiring`] and Hardfork. #[inline] pub fn into_db_and_env_with_handler_cfg( self, From 763592a45ebb8087bdd9c7e63062b261421f9175 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 12:27:51 +0200 Subject: [PATCH 58/59] final doc fix --- crates/revm/src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 49ae0e31ab..e3db22bed8 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -131,7 +131,7 @@ where EvmWiringT: EvmWiring>>, { - /// Sets the [`EmptyDB`] as the [`Database`] that will be used by [`Evm`]. + /// Creates the default [EvmWiring]::[crate::Database] that will be used by [`Evm`]. pub fn with_default_db(mut self) -> EvmBuilder<'a, SetGenericStage, EvmWiringT> where EvmWiringT::Database: Default, From 5fef8e221d246d5fa3bea4db65e4da8ebfe13a61 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 6 Sep 2024 12:42:06 +0200 Subject: [PATCH 59/59] rm alloy provider --- Cargo.lock | 1 - crates/optimism/Cargo.toml | 2 -- 2 files changed, 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12ebe50ecb..b7704eaa89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3139,7 +3139,6 @@ dependencies = [ name = "revm-optimism" version = "1.0.0" dependencies = [ - "alloy-provider", "alloy-sol-types", "anyhow", "criterion", diff --git a/crates/optimism/Cargo.toml b/crates/optimism/Cargo.toml index ca3fdd2ce6..01fe061821 100644 --- a/crates/optimism/Cargo.toml +++ b/crates/optimism/Cargo.toml @@ -45,8 +45,6 @@ indicatif = "0.17" rstest = "0.22.0" alloy-sol-types = "0.8" -alloy-provider = "0.3" - [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst"] std = [