diff --git a/Cargo.lock b/Cargo.lock index fa90de124f..ebecebcbe1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2970,6 +2970,7 @@ dependencies = [ name = "revm-context" version = "1.0.0" dependencies = [ + "cfg-if", "derive-where", "revm-bytecode", "revm-context-interface", @@ -2987,7 +2988,6 @@ name = "revm-context-interface" version = "1.0.0" dependencies = [ "auto_impl", - "cfg-if", "revm-database", "revm-database-interface", "revm-primitives", diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index eeb3e026a3..3b655dcb8e 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -7,11 +7,11 @@ use indicatif::{ProgressBar, ProgressDrawTarget}; use inspector::{inspector_handler, inspectors::TracerEip3155, InspectorContext, InspectorMainEvm}; use revm::{ bytecode::Bytecode, - context::{block::BlockEnv, tx::TxEnv}, + context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv}, context_interface::{ block::calc_excess_blob_gas, result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, - Cfg, CfgEnv, + Cfg, }, database_interface::EmptyDB, handler::EthHandler, diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 1fc05fe7cb..bd08b24cc0 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -33,6 +33,7 @@ bytecode.workspace = true # misc derive-where.workspace = true +cfg-if.workspace = true # Optional serde = { version = "1.0", default-features = false, features = [ @@ -44,13 +45,20 @@ serde = { version = "1.0", default-features = false, features = [ database.workspace = true [features] +# Implementation-specific features default = ["std"] -std = ["serde?/std"] -serde = [ - "dep:serde", - "primitives/serde", - "specification/serde", - "state/serde", - "context-interface/serde", +std = [] +dev = [ + "memory_limit", + "optional_balance_check", + "optional_block_gas_limit", + "optional_eip3607", + "optional_gas_refund", + "optional_no_base_fee", ] -serde-json = ["serde"] +memory_limit = [] +optional_balance_check = [] +optional_block_gas_limit = [] +optional_eip3607 = [] +optional_gas_refund = [] +optional_no_base_fee = [] diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 49d0a71bc0..6109090aa5 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -29,7 +29,6 @@ state.workspace = true specification.workspace = true # mics -cfg-if.workspace = true auto_impl.workspace = true # Optional @@ -47,20 +46,3 @@ std = ["serde?/std"] serde = ["dep:serde", "primitives/serde", "specification/serde", "state/serde"] serde-json = ["serde"] -# Enable additional features for development -# They add functions to Cfg trait. -dev = [ - "memory_limit", - "optional_balance_check", - "optional_block_gas_limit", - "optional_eip3607", - "optional_gas_refund", - "optional_no_base_fee", - -] -memory_limit = [] -optional_balance_check = [] -optional_block_gas_limit = [] -optional_eip3607 = [] -optional_gas_refund = [] -optional_no_base_fee = [] diff --git a/crates/context/interface/src/cfg.rs b/crates/context/interface/src/cfg.rs index 5fc8cbe6ad..b099c52c95 100644 --- a/crates/context/interface/src/cfg.rs +++ b/crates/context/interface/src/cfg.rs @@ -2,7 +2,7 @@ use auto_impl::auto_impl; use core::fmt::Debug; use core::hash::Hash; use primitives::{TxKind, U256}; -use specification::{constants::MAX_CODE_SIZE, hardfork::SpecId}; +use specification::hardfork::SpecId; #[auto_impl(&, &mut, Box, Arc)] pub trait Cfg { @@ -39,153 +39,6 @@ pub enum AnalysisKind { Analyse, } -/// EVM configuration. -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub struct CfgEnv = SpecId> { - /// Chain ID of the EVM, it will be compared to the transaction's Chain ID. - /// Chain ID is introduced EIP-155 - pub chain_id: u64, - /// Specification for EVM represent the hardfork. - pub spec: SPEC, - /// 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. - 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 - /// a sane value to prevent memory allocation panics. Defaults to `2^32 - 1` bytes per - /// EIP-1985. - #[cfg(feature = "memory_limit")] - pub memory_limit: u64, - /// Skip balance checks if true. Adds transaction cost to balance to ensure execution doesn't fail. - #[cfg(feature = "optional_balance_check")] - pub disable_balance_check: bool, - /// There are use cases where it's allowed to provide a gas limit that's higher than a block's gas limit. To that - /// end, you can disable the block gas limit validation. - /// By default, it is set to `false`. - #[cfg(feature = "optional_block_gas_limit")] - pub disable_block_gas_limit: bool, - /// EIP-3607 rejects transactions from senders with deployed code. In development, it can be desirable to simulate - /// calls from contracts, which this setting allows. - /// By default, it is set to `false`. - #[cfg(feature = "optional_eip3607")] - pub disable_eip3607: bool, - /// Disables all gas refunds. This is useful when using chains that have gas refunds disabled e.g. Avalanche. - /// Reasoning behind removing gas refunds can be found in EIP-3298. - /// By default, it is set to `false`. - #[cfg(feature = "optional_gas_refund")] - pub disable_gas_refund: bool, - /// Disables base fee checks for EIP-1559 transactions. - /// This is useful for testing method calls with zero gas price. - /// By default, it is set to `false`. - #[cfg(feature = "optional_no_base_fee")] - pub disable_base_fee: bool, -} - -impl CfgEnv { - pub fn with_chain_id(mut self, chain_id: u64) -> Self { - self.chain_id = chain_id; - self - } -} - -impl + Copy> Cfg for CfgEnv { - type Spec = SPEC; - - fn chain_id(&self) -> u64 { - self.chain_id - } - - fn spec(&self) -> Self::Spec { - self.spec - } - - fn max_code_size(&self) -> usize { - self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE) - } - - fn is_eip3607_disabled(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optional_eip3607")] { - self.disable_eip3607 - } else { - false - } - } - } - - fn is_balance_check_disabled(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optional_balance_check")] { - self.disable_balance_check - } else { - false - } - } - } - - fn is_gas_refund_disabled(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optional_gas_refund")] { - self.disable_gas_refund - } else { - false - } - } - } - - fn is_block_gas_limit_disabled(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optional_block_gas_limit")] { - self.disable_block_gas_limit - } else { - false - } - } - } - - fn is_nonce_check_disabled(&self) -> bool { - self.disable_nonce_check - } - - fn is_base_fee_check_disabled(&self) -> bool { - cfg_if::cfg_if! { - if #[cfg(feature = "optional_no_base_fee")] { - self.disable_base_fee - } else { - false - } - } - } -} - -impl Default for CfgEnv { - fn default() -> Self { - Self { - chain_id: 1, - limit_contract_code_size: None, - spec: SpecId::PRAGUE, - disable_nonce_check: false, - #[cfg(feature = "memory_limit")] - memory_limit: (1 << 32) - 1, - #[cfg(feature = "optional_balance_check")] - disable_balance_check: false, - #[cfg(feature = "optional_block_gas_limit")] - disable_block_gas_limit: false, - #[cfg(feature = "optional_eip3607")] - disable_eip3607: false, - #[cfg(feature = "optional_gas_refund")] - disable_gas_refund: false, - #[cfg(feature = "optional_no_base_fee")] - disable_base_fee: false, - } - } -} - /// Transaction destination pub type TransactTo = TxKind; diff --git a/crates/context/interface/src/lib.rs b/crates/context/interface/src/lib.rs index 8d1090fd9c..37f725ab9a 100644 --- a/crates/context/interface/src/lib.rs +++ b/crates/context/interface/src/lib.rs @@ -13,7 +13,7 @@ pub mod result; pub mod transaction; pub use block::{Block, BlockGetter}; -pub use cfg::{Cfg, CfgEnv, CfgGetter, CreateScheme, TransactTo}; +pub use cfg::{Cfg, CfgGetter, CreateScheme, TransactTo}; pub use database_interface::{DBErrorMarker, Database, DatabaseGetter}; pub use errors::ErrorGetter; pub use journaled_state::{JournalStateGetter, JournalStateGetterDBError, JournaledState}; diff --git a/crates/context/src/cfg.rs b/crates/context/src/cfg.rs index a4a82a1e92..9176a04cf4 100644 --- a/crates/context/src/cfg.rs +++ b/crates/context/src/cfg.rs @@ -1 +1,151 @@ -pub use context_interface::{Cfg, CfgEnv}; +pub use context_interface::Cfg; + +use interpreter::MAX_CODE_SIZE; +use specification::hardfork::SpecId; + +/// EVM configuration. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] +pub struct CfgEnv = SpecId> { + /// Chain ID of the EVM, it will be compared to the transaction's Chain ID. + /// Chain ID is introduced EIP-155 + pub chain_id: u64, + /// Specification for EVM represent the hardfork. + pub spec: SPEC, + /// 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. + pub disable_nonce_check: bool, + /// A hard memory limit in bytes beyond which [context_interface::result::OutOfGasError::Memory] cannot be resized. + /// + /// In cases where the gas limit may be extraordinarily high, it is recommended to set this to + /// a sane value to prevent memory allocation panics. Defaults to `2^32 - 1` bytes per + /// EIP-1985. + #[cfg(feature = "memory_limit")] + pub memory_limit: u64, + /// Skip balance checks if true. Adds transaction cost to balance to ensure execution doesn't fail. + #[cfg(feature = "optional_balance_check")] + pub disable_balance_check: bool, + /// There are use cases where it's allowed to provide a gas limit that's higher than a block's gas limit. To that + /// end, you can disable the block gas limit validation. + /// By default, it is set to `false`. + #[cfg(feature = "optional_block_gas_limit")] + pub disable_block_gas_limit: bool, + /// EIP-3607 rejects transactions from senders with deployed code. In development, it can be desirable to simulate + /// calls from contracts, which this setting allows. + /// By default, it is set to `false`. + #[cfg(feature = "optional_eip3607")] + pub disable_eip3607: bool, + /// Disables all gas refunds. This is useful when using chains that have gas refunds disabled e.g. Avalanche. + /// Reasoning behind removing gas refunds can be found in EIP-3298. + /// By default, it is set to `false`. + #[cfg(feature = "optional_gas_refund")] + pub disable_gas_refund: bool, + /// Disables base fee checks for EIP-1559 transactions. + /// This is useful for testing method calls with zero gas price. + /// By default, it is set to `false`. + #[cfg(feature = "optional_no_base_fee")] + pub disable_base_fee: bool, +} + +impl CfgEnv { + pub fn with_chain_id(mut self, chain_id: u64) -> Self { + self.chain_id = chain_id; + self + } +} + +impl + Copy> Cfg for CfgEnv { + type Spec = SPEC; + + fn chain_id(&self) -> u64 { + self.chain_id + } + + fn spec(&self) -> Self::Spec { + self.spec + } + + fn max_code_size(&self) -> usize { + self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE) + } + + fn is_eip3607_disabled(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optional_eip3607")] { + self.disable_eip3607 + } else { + false + } + } + } + + fn is_balance_check_disabled(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optional_balance_check")] { + self.disable_balance_check + } else { + false + } + } + } + + fn is_gas_refund_disabled(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optional_gas_refund")] { + self.disable_gas_refund + } else { + false + } + } + } + + fn is_block_gas_limit_disabled(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optional_block_gas_limit")] { + self.disable_block_gas_limit + } else { + false + } + } + } + + fn is_nonce_check_disabled(&self) -> bool { + self.disable_nonce_check + } + + fn is_base_fee_check_disabled(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "optional_no_base_fee")] { + self.disable_base_fee + } else { + false + } + } + } +} + +impl Default for CfgEnv { + fn default() -> Self { + Self { + chain_id: 1, + limit_contract_code_size: None, + spec: SpecId::PRAGUE, + disable_nonce_check: false, + #[cfg(feature = "memory_limit")] + memory_limit: (1 << 32) - 1, + #[cfg(feature = "optional_balance_check")] + disable_balance_check: false, + #[cfg(feature = "optional_block_gas_limit")] + disable_block_gas_limit: false, + #[cfg(feature = "optional_eip3607")] + disable_eip3607: false, + #[cfg(feature = "optional_gas_refund")] + disable_gas_refund: false, + #[cfg(feature = "optional_no_base_fee")] + disable_base_fee: false, + } + } +} diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 59d1801d07..3d8647b32e 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -1,11 +1,13 @@ -use crate::{block::BlockEnv, journaled_state::JournaledState as JournaledStateImpl, tx::TxEnv}; +use crate::{ + block::BlockEnv, cfg::CfgEnv, journaled_state::JournaledState as JournaledStateImpl, tx::TxEnv, +}; use bytecode::{Bytecode, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; use context_interface::{ block::BlockSetter, journaled_state::{AccountLoad, Eip7702CodeLoad}, result::EVMError, transaction::TransactionSetter, - Block, BlockGetter, Cfg, CfgEnv, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, + Block, BlockGetter, Cfg, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, Transaction, TransactionGetter, }; use database_interface::{Database, EmptyDB}; @@ -47,12 +49,13 @@ impl { pub fn new(db: DB, spec: SpecId) -> Self { - let mut cfg = CfgEnv::default(); - cfg.spec = spec; Self { tx: TX::default(), block: BLOCK::default(), - cfg, + cfg: CfgEnv { + spec, + ..Default::default() + }, journaled_state: JournaledStateImpl::new(SpecId::LATEST, db), chain: Default::default(), error: Ok(()), diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 4660ade64e..6c216024ca 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -3,13 +3,13 @@ use core::mem::MaybeUninit; use derive_where::derive_where; use revm::{ bytecode::opcode::OpCode, - context::{block::BlockEnv, tx::TxEnv, Cfg}, + context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv, Cfg}, context_interface::{ block::BlockSetter, journaled_state::{AccountLoad, Eip7702CodeLoad}, result::EVMError, transaction::TransactionSetter, - Block, BlockGetter, CfgEnv, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, + Block, BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, JournalStateGetterDBError, Transaction, TransactionGetter, }, database_interface::{Database, EmptyDB}, diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 3b04283ada..524101ea2f 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,5 +1,5 @@ use crate::{Host, SStoreResult, SelfDestructResult}; -use context_interface::{Block, Cfg, CfgEnv, Transaction}; +use context_interface::{Block, Cfg, Transaction}; use primitives::{hash_map::Entry, Address, Bytes, HashMap, Log, B256, KECCAK_EMPTY, U256}; use std::vec::Vec; @@ -21,10 +21,11 @@ where pub log: Vec, } -impl DummyHost +impl DummyHost where BLOCK: Block, TX: Transaction, + CFG: Cfg + Default, { /// Create a new dummy host with the given [`Transaction`] and [`Block`]. #[inline] @@ -32,7 +33,7 @@ where Self { tx, block, - cfg: CfgEnv::default(), + cfg: CFG::default(), storage: HashMap::default(), transient_storage: HashMap::default(), log: Vec::new(), diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index fd74481132..af76b91060 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -82,12 +82,12 @@ dev = [ "optional_gas_refund", "optional_no_base_fee", ] -memory_limit = ["context-interface/memory_limit", "interpreter/memory_limit"] -optional_balance_check = ["context-interface/optional_balance_check"] -optional_block_gas_limit = ["context-interface/optional_block_gas_limit"] -optional_eip3607 = ["context-interface/optional_eip3607"] -optional_gas_refund = ["context-interface/optional_gas_refund"] -optional_no_base_fee = ["context-interface/optional_no_base_fee"] +memory_limit = ["context/memory_limit", "interpreter/memory_limit"] +optional_balance_check = ["context/optional_balance_check"] +optional_block_gas_limit = ["context/optional_block_gas_limit"] +optional_eip3607 = ["context/optional_eip3607"] +optional_gas_refund = ["context/optional_gas_refund"] +optional_no_base_fee = ["context/optional_no_base_fee"] # See comments in `precompile` secp256k1 = ["precompile/secp256k1"]