diff --git a/Cargo.lock b/Cargo.lock index 8cae6fe6a8c68..6052c3f3f6a3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2985,7 +2985,9 @@ dependencies = [ "clap", "futures-util", "reth", + "reth-evm", "reth-node-ethereum", + "revm-primitives", ] [[package]] diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index 9cec2f9a92b71..2aaa063d745b9 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -198,7 +198,7 @@ mod tests { primitives::{BlockEnv, CfgEnv, SpecId}, JournaledState, }; - use revm_primitives::{EnvWithHandlerCfg, HandlerCfg}; + use revm_primitives::HandlerCfg; use std::collections::HashSet; #[test] @@ -272,12 +272,13 @@ mod tests { let db = CacheDB::>::default(); - let env_with_handler = EnvWithHandlerCfg::default(); + let evm_env = EvmEnv::default(); - let evm = evm_config.evm_with_env(db, env_with_handler.clone()); + let evm = evm_config.evm_with_env(db, evm_env.clone(), Default::default()); // Check that the EVM environment - assert_eq!(evm.context.evm.env, env_with_handler.env); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env); // Default spec ID assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -296,16 +297,15 @@ mod tests { // Create a custom configuration environment with a chain ID of 111 let cfg = CfgEnv::default().with_chain_id(111); - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { - cfg: cfg.clone(), - block: BlockEnv::default(), - tx: TxEnv::default(), - }), - handler_cfg: Default::default(), + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: cfg.clone(), + handler_cfg: Default::default(), + }, + ..Default::default() }; - let evm = evm_config.evm_with_env(db, env_with_handler); + let evm = evm_config.evm_with_env(db, evm_env, Default::default()); // Check that the EVM environment is initialized with the custom environment assert_eq!(evm.context.evm.inner.env.cfg, cfg); @@ -333,16 +333,19 @@ mod tests { }; let tx = TxEnv { gas_limit: 5_000_000, gas_price: U256::from(50), ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { cfg: CfgEnv::default(), block, tx }), - handler_cfg: Default::default(), + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: CfgEnv::default(), + handler_cfg: Default::default(), + }, + block_env: block, }; - let evm = evm_config.evm_with_env(db, env_with_handler.clone()); + let evm = evm_config.evm_with_env(db, evm_env.clone(), tx.clone()); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, env_with_handler.env.block); - assert_eq!(evm.context.evm.env.tx, env_with_handler.env.tx); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.tx, tx); // Default spec ID assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -360,9 +363,15 @@ mod tests { let handler_cfg = HandlerCfg { spec_id: SpecId::CONSTANTINOPLE, ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { env: Box::new(Env::default()), handler_cfg }; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: Default::default(), + handler_cfg, + }, + ..Default::default() + }; - let evm = evm_config.evm_with_env(db, env_with_handler); + let evm = evm_config.evm_with_env(db, evm_env, Default::default()); // Check that the spec ID is setup properly assert_eq!(evm.handler.spec_id(), SpecId::CONSTANTINOPLE); @@ -422,13 +431,18 @@ mod tests { let evm_config = EthEvmConfig::new(MAINNET.clone()); let db = CacheDB::>::default(); - let env_with_handler = EnvWithHandlerCfg::default(); + let evm_env = EvmEnv::default(); - let evm = - evm_config.evm_with_env_and_inspector(db, env_with_handler.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector( + db, + evm_env.clone(), + Default::default(), + NoOpInspector, + ); // Check that the EVM environment is set to default values - assert_eq!(evm.context.evm.env, env_with_handler.env); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env); assert_eq!(evm.context.external, NoOpInspector); assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -442,18 +456,21 @@ mod tests { let evm_config = EthEvmConfig::new(MAINNET.clone()); let db = CacheDB::>::default(); - let cfg = CfgEnv::default().with_chain_id(111); + let cfg_env = CfgEnv::default().with_chain_id(111); let block = BlockEnv::default(); let tx = TxEnv::default(); - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { cfg: cfg.clone(), block, tx }), - handler_cfg: Default::default(), + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: cfg_env.clone(), + handler_cfg: Default::default(), + }, + block_env: block, }; - let evm = evm_config.evm_with_env_and_inspector(db, env_with_handler, NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env, tx, NoOpInspector); // Check that the EVM environment is set with custom configuration - assert_eq!(evm.context.evm.env.cfg, cfg); + assert_eq!(evm.context.evm.env.cfg, cfg_env); assert_eq!(evm.context.external, NoOpInspector); assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -475,17 +492,14 @@ mod tests { ..Default::default() }; let tx = TxEnv { gas_limit: 5_000_000, gas_price: U256::from(50), ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { cfg: CfgEnv::default(), block, tx }), - handler_cfg: Default::default(), - }; + let evm_env = EvmEnv { block_env: block, ..Default::default() }; let evm = - evm_config.evm_with_env_and_inspector(db, env_with_handler.clone(), NoOpInspector); + evm_config.evm_with_env_and_inspector(db, evm_env.clone(), tx.clone(), NoOpInspector); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, env_with_handler.env.block); - assert_eq!(evm.context.evm.env.tx, env_with_handler.env.tx); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.tx, tx); assert_eq!(evm.context.external, NoOpInspector); assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -500,14 +514,26 @@ mod tests { let db = CacheDB::>::default(); let handler_cfg = HandlerCfg { spec_id: SpecId::CONSTANTINOPLE, ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { env: Box::new(Env::default()), handler_cfg }; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + handler_cfg, + cfg_env: Default::default(), + }, + ..Default::default() + }; - let evm = - evm_config.evm_with_env_and_inspector(db, env_with_handler.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector( + db, + evm_env.clone(), + Default::default(), + NoOpInspector, + ); // Check that the spec ID is set properly assert_eq!(evm.handler.spec_id(), SpecId::CONSTANTINOPLE); - assert_eq!(evm.context.evm.env, env_with_handler.env); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env); + assert_eq!(evm.context.evm.env.tx, Default::default()); assert_eq!(evm.context.external, NoOpInspector); // No Optimism diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index a4a02c3ef768f..fa219471bd84f 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -40,10 +40,7 @@ use reth_transaction_pool::{ }; use revm::{ db::{states::bundle_state::BundleRetention, State}, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, EVMError, EnvWithHandlerCfg, InvalidTransaction, - ResultAndState, TxEnv, - }, + primitives::{EVMError, InvalidTransaction, ResultAndState}, DatabaseCommit, }; use std::sync::Arc; @@ -108,7 +105,7 @@ where &self, args: BuildArguments, ) -> Result, PayloadBuilderError> { - let EvmEnv { cfg_env_with_handler_cfg, block_env } = self + let evm_env = self .cfg_and_block_env(&args.config, &args.config.parent_header) .map_err(PayloadBuilderError::other)?; @@ -117,8 +114,7 @@ where self.evm_config.clone(), self.builder_config.clone(), args, - cfg_env_with_handler_cfg, - block_env, + evm_env, |attributes| pool.best_transactions_with_attributes(attributes), ) } @@ -138,7 +134,7 @@ where None, ); - let EvmEnv { cfg_env_with_handler_cfg, block_env } = self + let evm_env = self .cfg_and_block_env(&args.config, &args.config.parent_header) .map_err(PayloadBuilderError::other)?; @@ -148,8 +144,7 @@ where self.evm_config.clone(), self.builder_config.clone(), args, - cfg_env_with_handler_cfg, - block_env, + evm_env, |attributes| pool.best_transactions_with_attributes(attributes), )? .into_payload() @@ -167,8 +162,7 @@ pub fn default_ethereum_payload( evm_config: EvmConfig, builder_config: EthereumBuilderConfig, args: BuildArguments, - initialized_cfg: CfgEnvWithHandlerCfg, - initialized_block_env: BlockEnv, + evm_env: EvmEnv, best_txs: F, ) -> Result, PayloadBuilderError> where @@ -189,19 +183,20 @@ where debug!(target: "payload_builder", id=%attributes.id, parent_header = ?parent_header.hash(), parent_number = parent_header.number, "building new payload"); let mut cumulative_gas_used = 0; let mut sum_blob_gas_used = 0; - let block_gas_limit: u64 = initialized_block_env.gas_limit.to::(); - let base_fee = initialized_block_env.basefee.to::(); + let block_gas_limit: u64 = evm_env.block_env.gas_limit.to::(); + let base_fee = evm_env.block_env.basefee.to::(); let mut executed_txs = Vec::new(); let mut executed_senders = Vec::new(); let mut best_txs = best_txs(BestTransactionsAttributes::new( base_fee, - initialized_block_env.get_blob_gasprice().map(|gasprice| gasprice as u64), + evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64), )); let mut total_fees = U256::ZERO; - let block_number = initialized_block_env.number.to::(); + let block_number = evm_env.block_env.number.to::(); + let beneficiary = evm_env.block_env.coinbase; let mut system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); @@ -209,8 +204,8 @@ where system_caller .pre_block_beacon_root_contract_call( &mut db, - &initialized_cfg, - &initialized_block_env, + evm_env.cfg_env_with_handler_cfg(), + evm_env.block_env(), attributes.parent_beacon_block_root, ) .map_err(|err| { @@ -225,8 +220,8 @@ where // apply eip-2935 blockhashes update system_caller.pre_block_blockhashes_contract_call( &mut db, - &initialized_cfg, - &initialized_block_env, + evm_env.cfg_env_with_handler_cfg(), + evm_env.block_env(), parent_header.hash(), ) .map_err(|err| { @@ -234,12 +229,7 @@ where PayloadBuilderError::Internal(err.into()) })?; - let env = EnvWithHandlerCfg::new_with_cfg_env( - initialized_cfg.clone(), - initialized_block_env.clone(), - TxEnv::default(), - ); - let mut evm = evm_config.evm_with_env(&mut db, env); + let mut evm = evm_config.evm_with_env(&mut db, evm_env, Default::default()); let mut receipts = Vec::new(); while let Some(pool_tx) = best_txs.next() { @@ -458,7 +448,7 @@ where let header = Header { parent_hash: parent_header.hash(), ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: initialized_block_env.coinbase, + beneficiary, state_root, transactions_root, receipts_root, diff --git a/crates/evm/src/env.rs b/crates/evm/src/env.rs index 7d6583a879ec2..ad41623a45676 100644 --- a/crates/evm/src/env.rs +++ b/crates/evm/src/env.rs @@ -9,6 +9,18 @@ pub struct EvmEnv { pub block_env: BlockEnv, } +impl Default for EvmEnv { + fn default() -> Self { + Self { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: Default::default(), + handler_cfg: Default::default(), + }, + block_env: BlockEnv::default(), + } + } +} + impl EvmEnv { /// Create a new `EvmEnv` from its components. /// diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index cd49785efd45b..f210ee24220ac 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -18,19 +18,18 @@ extern crate alloc; use crate::builder::RethEvmBuilder; -use alloc::boxed::Box; use alloy_consensus::BlockHeader as _; use alloy_primitives::{Address, Bytes, B256, U256}; use reth_primitives_traits::{BlockHeader, SignedTransaction}; use revm::{Database, Evm, GetInspector}; -use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, SpecId, TxEnv}; +use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, Env, SpecId, TxEnv}; pub mod builder; pub mod either; /// EVM environment configuration. pub mod env; pub mod execute; -use env::EvmEnv; +pub use env::EvmEnv; #[cfg(feature = "std")] pub mod metrics; @@ -56,10 +55,11 @@ pub trait ConfigureEvm: ConfigureEvmEnv { /// including the spec id. /// /// This will preserve any handler modifications - fn evm_with_env(&self, db: DB, env: EnvWithHandlerCfg) -> Evm<'_, (), DB> { + fn evm_with_env(&self, db: DB, evm_env: EvmEnv, tx: TxEnv) -> Evm<'_, (), DB> { let mut evm = self.evm(db); - evm.modify_spec_id(env.spec_id()); - evm.context.evm.env = env.env; + evm.modify_spec_id(evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id); + evm.context.evm.env = + Env::boxed(evm_env.cfg_env_with_handler_cfg.cfg_env, evm_env.block_env, tx); evm } @@ -71,17 +71,8 @@ pub trait ConfigureEvm: ConfigureEvmEnv { /// /// This does not initialize the tx environment. fn evm_for_block(&self, db: DB, header: &Self::Header) -> Evm<'_, (), DB> { - let EvmEnv { - cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { cfg_env, handler_cfg }, - block_env, - } = self.cfg_and_block_env(header); - self.evm_with_env( - db, - EnvWithHandlerCfg { - env: Box::new(Env { cfg: cfg_env, block: block_env, tx: Default::default() }), - handler_cfg, - }, - ) + let evm_env = self.cfg_and_block_env(header); + self.evm_with_env(db, evm_env, Default::default()) } /// Returns a new EVM with the given database configured with the given environment settings, @@ -93,7 +84,8 @@ pub trait ConfigureEvm: ConfigureEvmEnv { fn evm_with_env_and_inspector( &self, db: DB, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx: TxEnv, inspector: I, ) -> Evm<'_, I, DB> where @@ -101,8 +93,9 @@ pub trait ConfigureEvm: ConfigureEvmEnv { I: GetInspector, { let mut evm = self.evm_with_inspector(db, inspector); - evm.modify_spec_id(env.spec_id()); - evm.context.evm.env = env.env; + evm.modify_spec_id(evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id); + evm.context.evm.env = + Env::boxed(evm_env.cfg_env_with_handler_cfg.cfg_env, evm_env.block_env, tx); evm } @@ -133,21 +126,22 @@ where (*self).evm_for_block(db, header) } - fn evm_with_env(&self, db: DB, env: EnvWithHandlerCfg) -> Evm<'_, (), DB> { - (*self).evm_with_env(db, env) + fn evm_with_env(&self, db: DB, evm_env: EvmEnv, tx: TxEnv) -> Evm<'_, (), DB> { + (*self).evm_with_env(db, evm_env, tx) } fn evm_with_env_and_inspector( &self, db: DB, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx_env: TxEnv, inspector: I, ) -> Evm<'_, I, DB> where DB: Database, I: GetInspector, { - (*self).evm_with_env_and_inspector(db, env, inspector) + (*self).evm_with_env_and_inspector(db, evm_env, tx_env, inspector) } fn evm_with_inspector(&self, db: DB, inspector: I) -> Evm<'_, I, DB> diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index 9f7ead251562b..1c2cea5e8e7e5 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -211,7 +211,7 @@ mod tests { primitives::{AccountInfo, BlockEnv, CfgEnv, SpecId}, JournaledState, }; - use revm_primitives::{EnvWithHandlerCfg, HandlerCfg}; + use revm_primitives::HandlerCfg; use std::sync::Arc; fn test_evm_config() -> OpEvmConfig { @@ -291,12 +291,12 @@ mod tests { let db = CacheDB::>::default(); - let env_with_handler = EnvWithHandlerCfg::default(); + let evm_env = EvmEnv::default(); - let evm = evm_config.evm_with_env(db, env_with_handler.clone()); + let evm = evm_config.evm_with_env(db, evm_env.clone(), Default::default()); // Check that the EVM environment - assert_eq!(evm.context.evm.env, env_with_handler.env); + assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env); // Default spec ID assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -314,16 +314,15 @@ mod tests { // Create a custom configuration environment with a chain ID of 111 let cfg = CfgEnv::default().with_chain_id(111); - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { - cfg: cfg.clone(), - block: BlockEnv::default(), - tx: TxEnv::default(), - }), - handler_cfg: Default::default(), + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: cfg.clone(), + handler_cfg: Default::default(), + }, + ..Default::default() }; - let evm = evm_config.evm_with_env(db, env_with_handler); + let evm = evm_config.evm_with_env(db, evm_env, Default::default()); // Check that the EVM environment is initialized with the custom environment assert_eq!(evm.context.evm.inner.env.cfg, cfg); @@ -350,16 +349,13 @@ mod tests { }; let tx = TxEnv { gas_limit: 5_000_000, gas_price: U256::from(50), ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { cfg: CfgEnv::default(), block, tx }), - handler_cfg: Default::default(), - }; + let evm_env = EvmEnv { block_env: block, ..Default::default() }; - let evm = evm_config.evm_with_env(db, env_with_handler.clone()); + let evm = evm_config.evm_with_env(db, evm_env.clone(), tx.clone()); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, env_with_handler.env.block); - assert_eq!(evm.context.evm.env.tx, env_with_handler.env.tx); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.tx, tx); // Default spec ID assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -376,9 +372,15 @@ mod tests { let handler_cfg = HandlerCfg { spec_id: SpecId::ECOTONE, ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { env: Box::new(Env::default()), handler_cfg }; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + handler_cfg, + cfg_env: Default::default(), + }, + ..Default::default() + }; - let evm = evm_config.evm_with_env(db, env_with_handler); + let evm = evm_config.evm_with_env(db, evm_env, Default::default()); // Check that the spec ID is setup properly assert_eq!(evm.handler.spec_id(), SpecId::ECOTONE); @@ -436,13 +438,19 @@ mod tests { let evm_config = test_evm_config(); let db = CacheDB::>::default(); - let env_with_handler = EnvWithHandlerCfg::default(); + let evm_env = EvmEnv::default(); - let evm = - evm_config.evm_with_env_and_inspector(db, env_with_handler.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector( + db, + evm_env.clone(), + Default::default(), + NoOpInspector, + ); // Check that the EVM environment is set to default values - assert_eq!(evm.context.evm.env, env_with_handler.env); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env); + assert_eq!(evm.context.evm.env.tx, Default::default()); assert_eq!(evm.context.external, NoOpInspector); assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -458,15 +466,21 @@ mod tests { let cfg = CfgEnv::default().with_chain_id(111); let block = BlockEnv::default(); let tx = TxEnv::default(); - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { cfg: cfg.clone(), block, tx }), - handler_cfg: Default::default(), + let evm_env = EvmEnv { + block_env: block, + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: cfg.clone(), + handler_cfg: Default::default(), + }, }; - let evm = evm_config.evm_with_env_and_inspector(db, env_with_handler, NoOpInspector); + let evm = + evm_config.evm_with_env_and_inspector(db, evm_env.clone(), tx.clone(), NoOpInspector); // Check that the EVM environment is set with custom configuration assert_eq!(evm.context.evm.env.cfg, cfg); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.tx, tx); assert_eq!(evm.context.external, NoOpInspector); assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -487,17 +501,14 @@ mod tests { ..Default::default() }; let tx = TxEnv { gas_limit: 5_000_000, gas_price: U256::from(50), ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { - env: Box::new(Env { cfg: CfgEnv::default(), block, tx }), - handler_cfg: Default::default(), - }; + let evm_env = EvmEnv { block_env: block, ..Default::default() }; let evm = - evm_config.evm_with_env_and_inspector(db, env_with_handler.clone(), NoOpInspector); + evm_config.evm_with_env_and_inspector(db, evm_env.clone(), tx.clone(), NoOpInspector); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, env_with_handler.env.block); - assert_eq!(evm.context.evm.env.tx, env_with_handler.env.tx); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.context.evm.env.tx, tx); assert_eq!(evm.context.external, NoOpInspector); assert_eq!(evm.handler.spec_id(), SpecId::LATEST); @@ -511,14 +522,25 @@ mod tests { let db = CacheDB::>::default(); let handler_cfg = HandlerCfg { spec_id: SpecId::ECOTONE, ..Default::default() }; - let env_with_handler = EnvWithHandlerCfg { env: Box::new(Env::default()), handler_cfg }; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { + cfg_env: Default::default(), + handler_cfg, + }, + ..Default::default() + }; - let evm = - evm_config.evm_with_env_and_inspector(db, env_with_handler.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector( + db, + evm_env.clone(), + Default::default(), + NoOpInspector, + ); // Check that the spec ID is set properly assert_eq!(evm.handler.spec_id(), SpecId::ECOTONE); - assert_eq!(evm.context.evm.env, env_with_handler.env); + assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env_with_handler_cfg.cfg_env); + assert_eq!(evm.context.evm.env.block, evm_env.block_env); assert_eq!(evm.context.external, NoOpInspector); // Check that the spec ID is setup properly diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 7bf3f8015b711..08267240399bb 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -38,10 +38,7 @@ use reth_transaction_pool::{ }; use revm::{ db::{states::bundle_state::BundleRetention, State}, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, EVMError, EnvWithHandlerCfg, InvalidTransaction, - ResultAndState, TxEnv, - }, + primitives::{EVMError, InvalidTransaction, ResultAndState}, Database, DatabaseCommit, }; use std::{fmt::Display, sync::Arc}; @@ -127,7 +124,6 @@ where let evm_env = self .cfg_and_block_env(&args.config.attributes, &args.config.parent_header) .map_err(PayloadBuilderError::other)?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; let BuildArguments { client, pool: _, mut cached_reads, config, cancel, best_payload } = args; @@ -136,8 +132,7 @@ where evm_config: self.evm_config.clone(), chain_spec: client.chain_spec(), config, - initialized_cfg: cfg_env_with_handler_cfg, - initialized_block_env: block_env, + evm_env, cancel, best_payload, }; @@ -192,15 +187,13 @@ where let evm_env = self.cfg_and_block_env(&attributes, &parent).map_err(PayloadBuilderError::other)?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; let config = PayloadConfig { parent_header: Arc::new(parent), attributes }; let ctx = OpPayloadBuilderCtx { evm_config: self.evm_config.clone(), chain_spec: client.chain_spec(), config, - initialized_cfg: cfg_env_with_handler_cfg, - initialized_block_env: block_env, + evm_env, cancel: Default::default(), best_payload: Default::default(), }; @@ -402,7 +395,7 @@ where let header = Header { parent_hash: ctx.parent().hash(), ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: ctx.initialized_block_env.coinbase, + beneficiary: ctx.evm_env.block_env.coinbase, state_root, transactions_root, receipts_root, @@ -557,9 +550,7 @@ pub struct OpPayloadBuilderCtx { /// How to build the payload. pub config: PayloadConfig, /// Evm Settings - pub initialized_cfg: CfgEnvWithHandlerCfg, - /// Block config - pub initialized_block_env: BlockEnv, + pub evm_env: EvmEnv, /// Marker to check whether the job has been cancelled. pub cancel: Cancelled, /// The currently best payload. @@ -588,22 +579,22 @@ impl OpPayloadBuilderCtx { pub fn block_gas_limit(&self) -> u64 { self.attributes() .gas_limit - .unwrap_or_else(|| self.initialized_block_env.gas_limit.saturating_to()) + .unwrap_or_else(|| self.evm_env.block_env.gas_limit.saturating_to()) } /// Returns the block number for the block. pub fn block_number(&self) -> u64 { - self.initialized_block_env.number.to() + self.evm_env.block_env.number.to() } /// Returns the current base fee pub fn base_fee(&self) -> u64 { - self.initialized_block_env.basefee.to() + self.evm_env.block_env.basefee.to() } /// Returns the current blob gas price. pub fn get_blob_gasprice(&self) -> Option { - self.initialized_block_env.get_blob_gasprice().map(|gasprice| gasprice as u64) + self.evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64) } /// Returns the blob fields for the header. @@ -722,8 +713,8 @@ where SystemCaller::new(self.evm_config.clone(), self.chain_spec.clone()) .pre_block_beacon_root_contract_call( db, - &self.initialized_cfg, - &self.initialized_block_env, + &self.evm_env.cfg_env_with_handler_cfg, + &self.evm_env.block_env, self.attributes().payload_attributes.parent_beacon_block_root, ) .map_err(|err| { @@ -747,13 +738,8 @@ where DB: Database, { let mut info = ExecutionInfo::with_capacity(self.attributes().transactions.len()); - - let env = EnvWithHandlerCfg::new_with_cfg_env( - self.initialized_cfg.clone(), - self.initialized_block_env.clone(), - TxEnv::default(), - ); - let mut evm = self.evm_config.evm_with_env(&mut *db, env); + let mut evm = + self.evm_config.evm_with_env(&mut *db, self.evm_env.clone(), Default::default()); for sequencer_tx in &self.attributes().transactions { // A sequencer's block should never contain blob transactions. @@ -862,12 +848,8 @@ where let block_gas_limit = self.block_gas_limit(); let base_fee = self.base_fee(); - let env = EnvWithHandlerCfg::new_with_cfg_env( - self.initialized_cfg.clone(), - self.initialized_block_env.clone(), - TxEnv::default(), - ); - let mut evm = self.evm_config.evm_with_env(&mut *db, env); + let mut evm = + self.evm_config.evm_with_env(&mut *db, self.evm_env.clone(), Default::default()); while let Some(tx) = best_txs.next(()) { // ensure we still have capacity for this transaction diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index 91bedbeb532ea..538c980801491 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -41,6 +41,7 @@ use reth_rpc_eth_types::{ }; use revm::{Database, DatabaseCommit, GetInspector}; use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector}; +use revm_primitives::Env; use tracing::trace; /// Result type for `eth_simulateV1` RPC method. @@ -86,8 +87,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA } // Build cfg and block env, we'll reuse those. - let (evm_env, block) = self.evm_env_at(block.unwrap_or_default()).await?; - let EvmEnv { mut cfg_env_with_handler_cfg, mut block_env } = evm_env; + let (mut evm_env, block) = self.evm_env_at(block.unwrap_or_default()).await?; // Gas cap for entire operation let total_gas_limit = self.call_gas_limit(); @@ -97,9 +97,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let mut parent_hash = base_block.hash(); // Only enforce base fee if validation is enabled - cfg_env_with_handler_cfg.disable_base_fee = !validation; + evm_env.cfg_env_with_handler_cfg.disable_base_fee = !validation; // Always disable EIP-3607 - cfg_env_with_handler_cfg.disable_eip3607 = true; + evm_env.cfg_env_with_handler_cfg.disable_eip3607 = true; let this = self.clone(); self.spawn_with_state_at_block(block, move |state| { @@ -110,13 +110,13 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let mut block_state_calls = block_state_calls.into_iter().peekable(); while let Some(block) = block_state_calls.next() { // Increase number and timestamp for every new block - block_env.number += U256::from(1); - block_env.timestamp += U256::from(1); + evm_env.block_env.number += U256::from(1); + evm_env.block_env.timestamp += U256::from(1); if validation { let chain_spec = RpcNodeCore::provider(&this).chain_spec(); - let base_fee_params = - chain_spec.base_fee_params_at_timestamp(block_env.timestamp.to()); + let base_fee_params = chain_spec + .base_fee_params_at_timestamp(evm_env.block_env.timestamp.to()); let base_fee = if let Some(latest) = blocks.last() { let header = &latest.inner.header; calc_next_block_base_fee( @@ -128,21 +128,21 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA } else { base_block.next_block_base_fee(base_fee_params).unwrap_or_default() }; - block_env.basefee = U256::from(base_fee); + evm_env.block_env.basefee = U256::from(base_fee); } else { - block_env.basefee = U256::ZERO; + evm_env.block_env.basefee = U256::ZERO; } let SimBlock { block_overrides, state_overrides, calls } = block; if let Some(block_overrides) = block_overrides { - apply_block_overrides(block_overrides, &mut db, &mut block_env); + apply_block_overrides(block_overrides, &mut db, &mut evm_env.block_env); } if let Some(state_overrides) = state_overrides { apply_state_overrides(state_overrides, &mut db)?; } - if (total_gas_limit - gas_used) < block_env.gas_limit.to() { + if (total_gas_limit - gas_used) < evm_env.block_env.gas_limit.to() { return Err( EthApiError::Other(Box::new(EthSimulateError::GasLimitReached)).into() ) @@ -153,7 +153,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let txs_without_gas_limit = calls.iter().filter(|tx| tx.gas.is_none()).count(); - if total_specified_gas > block_env.gas_limit.to() { + if total_specified_gas > evm_env.block_env.gas_limit.to() { return Err(EthApiError::Other(Box::new( EthSimulateError::BlockGasLimitExceeded, )) @@ -161,7 +161,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA } if txs_without_gas_limit > 0 { - (block_env.gas_limit.to::() - total_specified_gas) / + (evm_env.block_env.gas_limit.to::() - total_specified_gas) / txs_without_gas_limit as u64 } else { 0 @@ -182,27 +182,23 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA call, validation, default_gas_limit, - cfg_env_with_handler_cfg.chain_id, + evm_env.cfg_env_with_handler_cfg.chain_id, &mut db, this.tx_resp_builder(), )?; let tx_env = this.evm_config().tx_env(&tx, sender); - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg.clone(), - block_env.clone(), - tx_env, - ); - let (res, env) = { + let (res, (_, tx_env)) = { if trace_transfers { this.transact_with_inspector( &mut db, - env, + evm_env.clone(), + tx_env, TransferInspector::new(false).with_logs(true), )? } else { - this.transact(&mut db, env)? + this.transact(&mut db, evm_env.clone(), tx_env.clone())? } }; @@ -213,12 +209,12 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA } transactions.push(tx); - senders.push(env.tx.caller); + senders.push(tx_env.caller); results.push(res.result); } let (block, _) = this.assemble_block_and_receipts( - &block_env, + &evm_env.block_env, parent_hash, // state root calculation is skipped for performance reasons B256::ZERO, @@ -300,7 +296,6 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA self.evm_env_at(target_block), self.block_with_senders(target_block) )?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; let block = block.ok_or(EthApiError::HeaderNotFound(target_block))?; @@ -330,12 +325,8 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA // to be replayed let transactions = block.transactions_with_sender().take(num_txs); for (signer, tx) in transactions { - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg.clone(), - block_env.clone(), - RpcNodeCore::evm_config(&this).tx_env(tx, *signer), - ); - let (res, _) = this.transact(&mut db, env)?; + let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx, *signer); + let (res, _) = this.transact(&mut db, evm_env.clone(), tx_env)?; db.commit(res.state); } } @@ -348,14 +339,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let state_overrides = state_override.take(); let overrides = EvmOverrides::new(state_overrides, block_overrides.clone()); - let env = this.prepare_call_env( - cfg_env_with_handler_cfg.clone(), - block_env.clone(), - tx, - &mut db, - overrides, - )?; - let (res, _) = this.transact(&mut db, env)?; + let (evm_env, tx) = + this.prepare_call_env(evm_env.clone(), tx, &mut db, overrides)?; + let (res, _) = this.transact(&mut db, evm_env, tx)?; match ensure_success(res.result) { Ok(output) => { @@ -395,12 +381,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA async move { let block_id = block_number.unwrap_or_default(); let (evm_env, at) = self.evm_env_at(block_id).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; - self.spawn_blocking_io(move |this| { - this.create_access_list_with(cfg_env_with_handler_cfg, block_env, at, request) - }) - .await + self.spawn_blocking_io(move |this| this.create_access_list_with(evm_env, at, request)) + .await } } @@ -408,8 +391,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA /// [`BlockId`]. fn create_access_list_with( &self, - cfg: CfgEnvWithHandlerCfg, - block: BlockEnv, + mut evm_env: EvmEnv, at: BlockId, mut request: TransactionRequest, ) -> Result @@ -418,23 +400,23 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA { let state = self.state_at_block_id(at)?; - let mut env = self.build_call_evm_env(cfg, block, request.clone())?; + let mut tx_env = self.create_txn_env(&evm_env.block_env, request.clone())?; // we want to disable this in eth_createAccessList, since this is common practice used by // other node impls and providers - env.cfg.disable_block_gas_limit = true; + evm_env.cfg_env_with_handler_cfg.disable_block_gas_limit = true; // The basefee should be ignored for eth_createAccessList // See: // - env.cfg.disable_base_fee = true; + evm_env.cfg_env_with_handler_cfg.disable_base_fee = true; let mut db = CacheDB::new(StateProviderDatabase::new(state)); - if request.gas.is_none() && env.tx.gas_price > U256::ZERO { - let cap = caller_gas_allowance(&mut db, &env.tx)?; + if request.gas.is_none() && tx_env.gas_price > U256::ZERO { + let cap = caller_gas_allowance(&mut db, &tx_env)?; // no gas limit was provided in the request, so we need to cap the request's gas limit - env.tx.gas_limit = cap.min(env.block.gas_limit).saturating_to(); + tx_env.gas_limit = cap.min(evm_env.block_env.gas_limit).saturating_to(); } let from = request.from.unwrap_or_default(); @@ -449,16 +431,17 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA // can consume the list since we're not using the request anymore let initial = request.access_list.take().unwrap_or_default(); - let precompiles = get_precompiles(env.handler_cfg.spec_id); + let precompiles = get_precompiles(evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id); let mut inspector = AccessListInspector::new(initial, from, to, precompiles); - let (result, mut env) = self.inspect(&mut db, env, &mut inspector)?; + let (result, (evm_env, mut tx_env)) = + self.inspect(&mut db, evm_env, tx_env, &mut inspector)?; let access_list = inspector.into_access_list(); - env.tx.access_list = access_list.to_vec(); + tx_env.access_list = access_list.to_vec(); match result.result { ExecutionResult::Halt { reason, gas_used } => { let error = - Some(RpcInvalidTransactionError::halt(reason, env.tx.gas_limit).to_string()); + Some(RpcInvalidTransactionError::halt(reason, tx_env.gas_limit).to_string()); return Ok(AccessListResult { access_list, gas_used: U256::from(gas_used), error }) } ExecutionResult::Revert { output, gas_used } => { @@ -469,11 +452,11 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA }; // transact again to get the exact gas used - let (result, env) = self.transact(&mut db, env)?; + let (result, (_, tx_env)) = self.transact(&mut db, evm_env, tx_env)?; let res = match result.result { ExecutionResult::Halt { reason, gas_used } => { let error = - Some(RpcInvalidTransactionError::halt(reason, env.tx.gas_limit).to_string()); + Some(RpcInvalidTransactionError::halt(reason, tx_env.gas_limit).to_string()); AccessListResult { access_list, gas_used: U256::from(gas_used), error } } ExecutionResult::Revert { output, gas_used } => { @@ -515,16 +498,25 @@ pub trait Call: fn transact( &self, db: DB, - env: EnvWithHandlerCfg, - ) -> Result<(ResultAndState, EnvWithHandlerCfg), Self::Error> + evm_env: EvmEnv, + tx_env: TxEnv, + ) -> Result<(ResultAndState, (EvmEnv, TxEnv)), Self::Error> where DB: Database, EthApiError: From, { - let mut evm = self.evm_config().evm_with_env(db, env); + let mut evm = self.evm_config().evm_with_env(db, evm_env, tx_env); let res = evm.transact().map_err(Self::Error::from_evm_err)?; let (_, env) = evm.into_db_and_env_with_handler_cfg(); - Ok((res, env)) + + let EnvWithHandlerCfg { env, handler_cfg } = env; + let Env { cfg, block, tx } = *env; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { cfg_env: cfg, handler_cfg }, + block_env: block, + }; + + Ok((res, (evm_env, tx))) } /// Executes the [`EnvWithHandlerCfg`] against the given [Database] without committing state @@ -532,17 +524,26 @@ pub trait Call: fn transact_with_inspector( &self, db: DB, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx_env: TxEnv, inspector: impl GetInspector, - ) -> Result<(ResultAndState, EnvWithHandlerCfg), Self::Error> + ) -> Result<(ResultAndState, (EvmEnv, TxEnv)), Self::Error> where DB: Database, EthApiError: From, { - let mut evm = self.evm_config().evm_with_env_and_inspector(db, env, inspector); + let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, tx_env, inspector); let res = evm.transact().map_err(Self::Error::from_evm_err)?; let (_, env) = evm.into_db_and_env_with_handler_cfg(); - Ok((res, env)) + + let EnvWithHandlerCfg { env, handler_cfg } = env; + let Env { cfg, block, tx } = *env; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { cfg_env: cfg, handler_cfg }, + block_env: block, + }; + + Ok((res, (evm_env, tx))) } /// Executes the call request at the given [`BlockId`]. @@ -551,12 +552,14 @@ pub trait Call: request: TransactionRequest, at: BlockId, overrides: EvmOverrides, - ) -> impl Future> + Send + ) -> impl Future> + Send where Self: LoadPendingBlock, { let this = self.clone(); - self.spawn_with_call_at(request, at, overrides, move |db, env| this.transact(db, env)) + self.spawn_with_call_at(request, at, overrides, move |db, evm_env, tx_env| { + this.transact(db, evm_env, tx_env) + }) } /// Executes the closure with the state that corresponds to the given [`BlockId`] on a new task @@ -599,29 +602,23 @@ pub trait Call: ) -> impl Future> + Send where Self: LoadPendingBlock, - F: FnOnce(StateCacheDbRefMutWrapper<'_, '_>, EnvWithHandlerCfg) -> Result + F: FnOnce(StateCacheDbRefMutWrapper<'_, '_>, EvmEnv, TxEnv) -> Result + Send + 'static, R: Send + 'static, { async move { let (evm_env, at) = self.evm_env_at(at).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; let this = self.clone(); self.spawn_blocking_io(move |_| { let state = this.state_at_block_id(at)?; let mut db = CacheDB::new(StateProviderDatabase::new(StateProviderTraitObjWrapper(&state))); - let env = this.prepare_call_env( - cfg_env_with_handler_cfg, - block_env, - request, - &mut db, - overrides, - )?; + let (evm_env, tx_env) = + this.prepare_call_env(evm_env, request, &mut db, overrides)?; - f(StateCacheDbRefMutWrapper(&mut db), env) + f(StateCacheDbRefMutWrapper(&mut db), evm_env, tx_env) }) .await } @@ -656,7 +653,6 @@ pub trait Call: let (tx, tx_info) = transaction.split(); let (evm_env, _) = self.evm_env_at(block.hash().into()).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; // we need to get the state of the parent block because we're essentially replaying the // block the transaction is included in @@ -668,21 +664,11 @@ pub trait Call: let block_txs = block.transactions_with_sender(); // replay all transactions prior to the targeted transaction - this.replay_transactions_until( - &mut db, - cfg_env_with_handler_cfg.clone(), - block_env.clone(), - block_txs, - *tx.tx_hash(), - )?; - - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg, - block_env, - RpcNodeCore::evm_config(&this).tx_env(tx.tx(), tx.signer()), - ); - - let (res, _) = this.transact(&mut db, env)?; + this.replay_transactions_until(&mut db, evm_env.clone(), block_txs, *tx.tx_hash())?; + + let tx_env = RpcNodeCore::evm_config(&this).tx_env(tx.tx(), tx.signer()); + + let (res, _) = this.transact(&mut db, evm_env, tx_env)?; f(tx_info, res, db) }) .await @@ -700,8 +686,7 @@ pub trait Call: fn replay_transactions_until<'a, DB, I>( &self, db: &mut DB, - cfg: CfgEnvWithHandlerCfg, - block_env: BlockEnv, + evm_env: EvmEnv, transactions: I, target_tx_hash: B256, ) -> Result @@ -711,9 +696,7 @@ pub trait Call: I: IntoIterator::Transaction)>, ::Transaction: SignedTransaction, { - let env = EnvWithHandlerCfg::new_with_cfg_env(cfg, block_env, Default::default()); - - let mut evm = self.evm_config().evm_with_env(db, env); + let mut evm = self.evm_config().evm_with_env(db, evm_env, Default::default()); let mut index = 0; for (sender, tx) in transactions { if *tx.tx_hash() == target_tx_hash { @@ -807,20 +790,6 @@ pub trait Call: Ok(env) } - /// Creates a new [`EnvWithHandlerCfg`] to be used for executing the [`TransactionRequest`] in - /// `eth_call`. - /// - /// Note: this does _not_ access the Database to check the sender. - fn build_call_evm_env( - &self, - cfg: CfgEnvWithHandlerCfg, - block: BlockEnv, - request: TransactionRequest, - ) -> Result { - let tx = self.create_txn_env(&block, request)?; - Ok(EnvWithHandlerCfg::new_with_cfg_env(cfg, block, tx)) - } - /// Prepares the [`EnvWithHandlerCfg`] for execution of calls. /// /// Does not commit any changes to the underlying database. @@ -836,12 +805,11 @@ pub trait Call: /// In addition, this changes the block's gas limit to the configured [`Self::call_gas_limit`]. fn prepare_call_env( &self, - mut cfg: CfgEnvWithHandlerCfg, - mut block: BlockEnv, + mut evm_env: EvmEnv, mut request: TransactionRequest, db: &mut CacheDB, overrides: EvmOverrides, - ) -> Result + ) -> Result<(EvmEnv, TxEnv), Self::Error> where DB: DatabaseRef, EthApiError: From<::Error>, @@ -854,41 +822,41 @@ pub trait Call: } // apply configured gas cap - block.gas_limit = U256::from(self.call_gas_limit()); + evm_env.block_env.gas_limit = U256::from(self.call_gas_limit()); // Disabled because eth_call is sometimes used with eoa senders // See - cfg.disable_eip3607 = true; + evm_env.cfg_env_with_handler_cfg.disable_eip3607 = true; // The basefee should be ignored for eth_call // See: // - cfg.disable_base_fee = true; + evm_env.cfg_env_with_handler_cfg.disable_base_fee = true; // set nonce to None so that the correct nonce is chosen by the EVM request.nonce = None; if let Some(block_overrides) = overrides.block { - apply_block_overrides(*block_overrides, db, &mut block); + apply_block_overrides(*block_overrides, db, &mut evm_env.block_env); } if let Some(state_overrides) = overrides.state { apply_state_overrides(state_overrides, db)?; } let request_gas = request.gas; - let mut env = self.build_call_evm_env(cfg, block, request)?; + let mut tx_env = self.create_txn_env(&evm_env.block_env, request)?; if request_gas.is_none() { // No gas limit was provided in the request, so we need to cap the transaction gas limit - if env.tx.gas_price > U256::ZERO { + if tx_env.gas_price > U256::ZERO { // If gas price is specified, cap transaction gas limit with caller allowance - trace!(target: "rpc::eth::call", ?env, "Applying gas limit cap with caller allowance"); - let cap = caller_gas_allowance(db, &env.tx)?; + trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance"); + let cap = caller_gas_allowance(db, &tx_env)?; // ensure we cap gas_limit to the block's - env.tx.gas_limit = cap.min(env.block.gas_limit).saturating_to(); + tx_env.gas_limit = cap.min(evm_env.block_env.gas_limit).saturating_to(); } } - Ok(env) + Ok((evm_env, tx_env)) } } diff --git a/crates/rpc/rpc-eth-api/src/helpers/estimate.rs b/crates/rpc/rpc-eth-api/src/helpers/estimate.rs index fe2fa482d54d7..f8fc02ce3625d 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/estimate.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/estimate.rs @@ -11,14 +11,14 @@ use reth_provider::StateProvider; use reth_revm::{ database::StateProviderDatabase, db::CacheDB, - primitives::{BlockEnv, CfgEnvWithHandlerCfg, ExecutionResult, HaltReason, TransactTo}, + primitives::{ExecutionResult, HaltReason, TransactTo}, }; use reth_rpc_eth_types::{ revm_utils::{apply_state_overrides, caller_gas_allowance}, EthApiError, RevertError, RpcInvalidTransactionError, }; use reth_rpc_server_types::constants::gas_oracle::{CALL_STIPEND_GAS, ESTIMATE_GAS_ERROR_RATIO}; -use revm_primitives::{db::Database, EnvWithHandlerCfg}; +use revm_primitives::{db::Database, TxEnv}; use tracing::trace; /// Gas execution estimates @@ -36,8 +36,7 @@ pub trait EstimateCall: Call { /// - `nonce` is set to `None` fn estimate_gas_with( &self, - mut cfg: CfgEnvWithHandlerCfg, - block: BlockEnv, + mut evm_env: EvmEnv, mut request: TransactionRequest, state: S, state_override: Option, @@ -47,12 +46,12 @@ pub trait EstimateCall: Call { { // Disabled because eth_estimateGas is sometimes used with eoa senders // See - cfg.disable_eip3607 = true; + evm_env.cfg_env_with_handler_cfg.disable_eip3607 = true; // The basefee should be ignored for eth_estimateGas and similar // See: // - cfg.disable_base_fee = true; + evm_env.cfg_env_with_handler_cfg.disable_base_fee = true; // set nonce to None so that the correct nonce is chosen by the EVM request.nonce = None; @@ -61,7 +60,7 @@ pub trait EstimateCall: Call { let tx_request_gas_limit = request.gas.map(U256::from); let tx_request_gas_price = request.gas_price; // the gas limit of the corresponding block - let block_env_gas_limit = block.gas_limit; + let block_env_gas_limit = evm_env.block_env.gas_limit; // Determine the highest possible gas limit, considering both the request's specified limit // and the block's limit. @@ -76,7 +75,7 @@ pub trait EstimateCall: Call { .unwrap_or(block_env_gas_limit); // Configure the evm env - let mut env = self.build_call_evm_env(cfg, block, request)?; + let mut tx_env = self.create_txn_env(&evm_env.block_env, request)?; let mut db = CacheDB::new(StateProviderDatabase::new(state)); // Apply any state overrides if specified. @@ -85,8 +84,8 @@ pub trait EstimateCall: Call { } // Optimize for simple transfer transactions, potentially reducing the gas estimate. - if env.tx.data.is_empty() { - if let TransactTo::Call(to) = env.tx.transact_to { + if tx_env.data.is_empty() { + if let TransactTo::Call(to) = tx_env.transact_to { if let Ok(code) = db.db.account_code(&to) { let no_code_callee = code.map(|code| code.is_empty()).unwrap_or(true); if no_code_callee { @@ -95,9 +94,9 @@ pub trait EstimateCall: Call { // `MIN_TRANSACTION_GAS` is dangerous because there might be additional // field combos that bump the price up, so we try executing the function // with the minimum gas limit to make sure. - let mut env = env.clone(); - env.tx.gas_limit = MIN_TRANSACTION_GAS; - if let Ok((res, _)) = self.transact(&mut db, env) { + let mut tx_env = tx_env.clone(); + tx_env.gas_limit = MIN_TRANSACTION_GAS; + if let Ok((res, _)) = self.transact(&mut db, evm_env.clone(), tx_env) { if res.result.is_success() { return Ok(U256::from(MIN_TRANSACTION_GAS)) } @@ -110,35 +109,41 @@ pub trait EstimateCall: Call { // Check funds of the sender (only useful to check if transaction gas price is more than 0). // // The caller allowance is check by doing `(account.balance - tx.value) / tx.gas_price` - if env.tx.gas_price > U256::ZERO { + if tx_env.gas_price > U256::ZERO { // cap the highest gas limit by max gas caller can afford with given gas price highest_gas_limit = highest_gas_limit - .min(caller_gas_allowance(&mut db, &env.tx).map_err(Self::Error::from_eth_err)?); + .min(caller_gas_allowance(&mut db, &tx_env).map_err(Self::Error::from_eth_err)?); } // We can now normalize the highest gas limit to a u64 let mut highest_gas_limit = highest_gas_limit.saturating_to::(); // If the provided gas limit is less than computed cap, use that - env.tx.gas_limit = env.tx.gas_limit.min(highest_gas_limit); + tx_env.gas_limit = tx_env.gas_limit.min(highest_gas_limit); - trace!(target: "rpc::eth::estimate", ?env, "Starting gas estimation"); + trace!(target: "rpc::eth::estimate", ?evm_env, ?tx_env, "Starting gas estimation"); // Execute the transaction with the highest possible gas limit. - let (mut res, mut env) = match self.transact(&mut db, env.clone()) { - // Handle the exceptional case where the transaction initialization uses too much gas. - // If the gas price or gas limit was specified in the request, retry the transaction - // with the block's gas limit to determine if the failure was due to - // insufficient gas. - Err(err) - if err.is_gas_too_high() && - (tx_request_gas_limit.is_some() || tx_request_gas_price.is_some()) => - { - return Err(self.map_out_of_gas_err(block_env_gas_limit, env, &mut db)) - } - // Propagate other results (successful or other errors). - ethres => ethres?, - }; + let (mut res, (mut evm_env, mut tx_env)) = + match self.transact(&mut db, evm_env.clone(), tx_env.clone()) { + // Handle the exceptional case where the transaction initialization uses too much + // gas. If the gas price or gas limit was specified in the request, + // retry the transaction with the block's gas limit to determine if + // the failure was due to insufficient gas. + Err(err) + if err.is_gas_too_high() && + (tx_request_gas_limit.is_some() || tx_request_gas_price.is_some()) => + { + return Err(self.map_out_of_gas_err( + block_env_gas_limit, + evm_env, + tx_env, + &mut db, + )) + } + // Propagate other results (successful or other errors). + ethres => ethres?, + }; let gas_refund = match res.result { ExecutionResult::Success { gas_refunded, .. } => gas_refunded, @@ -151,7 +156,7 @@ pub trait EstimateCall: Call { // if price or limit was included in the request then we can execute the request // again with the block's gas limit to check if revert is gas related or not return if tx_request_gas_limit.is_some() || tx_request_gas_price.is_some() { - Err(self.map_out_of_gas_err(block_env_gas_limit, env, &mut db)) + Err(self.map_out_of_gas_err(block_env_gas_limit, evm_env, tx_env, &mut db)) } else { // the transaction did revert Err(RpcInvalidTransactionError::Revert(RevertError::new(output)).into_eth_err()) @@ -164,7 +169,7 @@ pub trait EstimateCall: Call { // we know the tx succeeded with the configured gas limit, so we can use that as the // highest, in case we applied a gas cap due to caller allowance above - highest_gas_limit = env.tx.gas_limit; + highest_gas_limit = tx_env.gas_limit; // NOTE: this is the gas the transaction used, which is less than the // transaction requires to succeed. @@ -181,10 +186,10 @@ pub trait EstimateCall: Call { let optimistic_gas_limit = (gas_used + gas_refund + CALL_STIPEND_GAS) * 64 / 63; if optimistic_gas_limit < highest_gas_limit { // Set the transaction's gas limit to the calculated optimistic gas limit. - env.tx.gas_limit = optimistic_gas_limit; + tx_env.gas_limit = optimistic_gas_limit; // Re-execute the transaction with the new gas limit and update the result and // environment. - (res, env) = self.transact(&mut db, env)?; + (res, (evm_env, tx_env)) = self.transact(&mut db, evm_env, tx_env)?; // Update the gas used based on the new result. gas_used = res.result.gas_used(); // Update the gas limit estimates (highest and lowest) based on the execution result. @@ -202,7 +207,7 @@ pub trait EstimateCall: Call { ((highest_gas_limit as u128 + lowest_gas_limit as u128) / 2) as u64, ); - trace!(target: "rpc::eth::estimate", ?env, ?highest_gas_limit, ?lowest_gas_limit, ?mid_gas_limit, "Starting binary search for gas"); + trace!(target: "rpc::eth::estimate", ?evm_env, ?tx_env, ?highest_gas_limit, ?lowest_gas_limit, ?mid_gas_limit, "Starting binary search for gas"); // Binary search narrows the range to find the minimum gas limit needed for the transaction // to succeed. @@ -216,10 +221,10 @@ pub trait EstimateCall: Call { break }; - env.tx.gas_limit = mid_gas_limit; + tx_env.gas_limit = mid_gas_limit; // Execute transaction and handle potential gas errors, adjusting limits accordingly. - match self.transact(&mut db, env.clone()) { + match self.transact(&mut db, evm_env.clone(), tx_env.clone()) { Err(err) if err.is_gas_too_high() => { // Decrease the highest gas limit if gas is too high highest_gas_limit = mid_gas_limit; @@ -231,7 +236,7 @@ pub trait EstimateCall: Call { // Handle other cases, including successful transactions. ethres => { // Unpack the result and environment if the transaction was successful. - (res, env) = ethres?; + (res, (evm_env, tx_env)) = ethres?; // Update the estimated gas range based on the transaction result. update_estimated_gas_range( res.result, @@ -261,18 +266,10 @@ pub trait EstimateCall: Call { { async move { let (evm_env, at) = self.evm_env_at(at).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; self.spawn_blocking_io(move |this| { let state = this.state_at_block_id(at)?; - EstimateCall::estimate_gas_with( - &this, - cfg_env_with_handler_cfg, - block_env, - request, - state, - state_override, - ) + EstimateCall::estimate_gas_with(&this, evm_env, request, state, state_override) }) .await } @@ -284,16 +281,17 @@ pub trait EstimateCall: Call { fn map_out_of_gas_err( &self, env_gas_limit: U256, - mut env: EnvWithHandlerCfg, + evm_env: EvmEnv, + mut tx_env: TxEnv, db: &mut DB, ) -> Self::Error where DB: Database, EthApiError: From, { - let req_gas_limit = env.tx.gas_limit; - env.tx.gas_limit = env_gas_limit.try_into().unwrap_or(u64::MAX); - let (res, _) = match self.transact(db, env) { + let req_gas_limit = tx_env.gas_limit; + tx_env.gas_limit = env_gas_limit.try_into().unwrap_or(u64::MAX); + let (res, _) = match self.transact(db, evm_env, tx_env) { Ok(res) => res, Err(err) => return err, }; diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index bb4c9c5ebf58d..d3f25928d1f12 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -2,7 +2,7 @@ use std::{fmt::Display, sync::Arc}; -use crate::{FromEvmError, RpcNodeCore}; +use crate::FromEvmError; use alloy_consensus::BlockHeader; use alloy_primitives::B256; use alloy_rpc_types_eth::{BlockId, TransactionInfo}; @@ -20,7 +20,7 @@ use reth_rpc_eth_types::{ use revm::{db::CacheDB, Database, DatabaseCommit, GetInspector, Inspector}; use revm_inspectors::tracing::{TracingInspector, TracingInspectorConfig}; use revm_primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, EvmState, ExecutionResult, ResultAndState, + CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, EvmState, ExecutionResult, ResultAndState, TxEnv, }; use super::{Call, LoadBlock, LoadPendingBlock, LoadState, LoadTransaction}; @@ -40,38 +40,25 @@ pub trait Trace: fn inspect( &self, db: DB, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx_env: TxEnv, inspector: I, - ) -> Result<(ResultAndState, EnvWithHandlerCfg), Self::Error> + ) -> Result<(ResultAndState, (EvmEnv, TxEnv)), Self::Error> where DB: Database, EthApiError: From, I: GetInspector, { - self.inspect_and_return_db(db, env, inspector).map(|(res, env, _)| (res, env)) - } - - /// Same as [`inspect`](Self::inspect) but also returns the database again. - /// - /// Even though [Database] is also implemented on `&mut` - /// this is still useful if there are certain trait bounds on the Inspector's database generic - /// type - fn inspect_and_return_db( - &self, - db: DB, - env: EnvWithHandlerCfg, - inspector: I, - ) -> Result<(ResultAndState, EnvWithHandlerCfg, DB), Self::Error> - where - DB: Database, - EthApiError: From, - - I: GetInspector, - { - let mut evm = self.evm_config().evm_with_env_and_inspector(db, env, inspector); + let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env, tx_env, inspector); let res = evm.transact().map_err(Self::Error::from_evm_err)?; - let (db, env) = evm.into_db_and_env_with_handler_cfg(); - Ok((res, env, db)) + let (_, env) = evm.into_db_and_env_with_handler_cfg(); + let EnvWithHandlerCfg { env, handler_cfg } = env; + let Env { cfg, block, tx } = *env; + let evm_env = EvmEnv { + cfg_env_with_handler_cfg: CfgEnvWithHandlerCfg { cfg_env: cfg, handler_cfg }, + block_env: block, + }; + Ok((res, (evm_env, tx))) } /// Executes the transaction on top of the given [`BlockId`] with a tracer configured by the @@ -83,7 +70,8 @@ pub trait Trace: /// Caution: this is blocking fn trace_at( &self, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx_env: TxEnv, config: TracingInspectorConfig, at: BlockId, f: F, @@ -95,7 +83,7 @@ pub trait Trace: self.with_state_at_block(at, |state| { let mut db = CacheDB::new(StateProviderDatabase::new(state)); let mut inspector = TracingInspector::new(config); - let (res, _) = self.inspect(&mut db, env, &mut inspector)?; + let (res, _) = self.inspect(&mut db, evm_env, tx_env, &mut inspector)?; f(inspector, res) }) } @@ -109,7 +97,8 @@ pub trait Trace: /// the configured [`EnvWithHandlerCfg`] was inspected. fn spawn_trace_at_with_state( &self, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx_env: TxEnv, config: TracingInspectorConfig, at: BlockId, f: F, @@ -125,7 +114,7 @@ pub trait Trace: self.spawn_with_state_at_block(at, move |state| { let mut db = CacheDB::new(StateProviderDatabase::new(state)); let mut inspector = TracingInspector::new(config); - let (res, _) = this.inspect(&mut db, env, &mut inspector)?; + let (res, _) = this.inspect(&mut db, evm_env, tx_env, &mut inspector)?; f(inspector, res, db) }) } @@ -196,7 +185,6 @@ pub trait Trace: let (tx, tx_info) = transaction.split(); let (evm_env, _) = self.evm_env_at(block.hash().into()).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; // we need to get the state of the parent block because we're essentially replaying the // block the transaction is included in @@ -207,29 +195,18 @@ pub trait Trace: let mut db = CacheDB::new(StateProviderDatabase::new(state)); let block_txs = block.transactions_with_sender(); - this.apply_pre_execution_changes( - &block, - &mut db, - &cfg_env_with_handler_cfg, - &block_env, - )?; + this.apply_pre_execution_changes(&block, &mut db, &evm_env)?; // replay all transactions prior to the targeted transaction - this.replay_transactions_until( - &mut db, - cfg_env_with_handler_cfg.clone(), - block_env.clone(), - block_txs, - *tx.tx_hash(), + this.replay_transactions_until(&mut db, evm_env.clone(), block_txs, *tx.tx_hash())?; + + let tx_env = this.evm_config().tx_env(tx.tx(), tx.signer()); + let (res, _) = this.inspect( + StateCacheDbRefMutWrapper(&mut db), + evm_env, + tx_env, + &mut inspector, )?; - - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg, - block_env, - RpcNodeCore::evm_config(&this).tx_env(tx.tx(), tx.signer()), - ); - let (res, _) = - this.inspect(StateCacheDbRefMutWrapper(&mut db), env, &mut inspector)?; f(tx_info, inspector, res, db) }) .await @@ -316,8 +293,6 @@ pub trait Trace: let ((evm_env, _), block) = futures::try_join!(self.evm_env_at(block_id), block)?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; - let Some(block) = block else { return Ok(None) }; if block.body().transactions().is_empty() { @@ -332,20 +307,15 @@ pub trait Trace: let state_at = block.parent_hash(); let block_hash = block.hash(); - let block_number = block_env.number.saturating_to::(); - let base_fee = block_env.basefee.saturating_to::(); + let block_number = evm_env.block_env.number.saturating_to::(); + let base_fee = evm_env.block_env.basefee.saturating_to::(); // now get the state let state = this.state_at_block_id(state_at.into())?; let mut db = CacheDB::new(StateProviderDatabase::new(StateProviderTraitObjWrapper(&state))); - this.apply_pre_execution_changes( - &block, - &mut db, - &cfg_env_with_handler_cfg, - &block_env, - )?; + this.apply_pre_execution_changes(&block, &mut db, &evm_env)?; // prepare transactions, we do everything upfront to reduce time spent with open // state @@ -374,15 +344,13 @@ pub trait Trace: .peekable(); while let Some((tx_info, tx)) = transactions.next() { - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg.clone(), - block_env.clone(), - tx, - ); - let mut inspector = inspector_setup(); - let (res, _) = - this.inspect(StateCacheDbRefMutWrapper(&mut db), env, &mut inspector)?; + let (res, _) = this.inspect( + StateCacheDbRefMutWrapper(&mut db), + evm_env.clone(), + tx, + &mut inspector, + )?; let ResultAndState { result, state } = res; results.push(f(tx_info, inspector, result, &state, &db)?); @@ -485,8 +453,7 @@ pub trait Trace: &self, block: &SealedBlockWithSenders>, db: &mut DB, - cfg: &CfgEnvWithHandlerCfg, - block_env: &BlockEnv, + evm_env: &EvmEnv, ) -> Result<(), Self::Error> { let mut system_caller = SystemCaller::new(self.evm_config().clone(), self.provider().chain_spec()); @@ -494,14 +461,19 @@ pub trait Trace: system_caller .pre_block_beacon_root_contract_call( db, - cfg, - block_env, + evm_env.cfg_env_with_handler_cfg(), + evm_env.block_env(), block.parent_beacon_block_root(), ) .map_err(|_| EthApiError::EvmCustom("failed to apply 4788 system call".to_string()))?; system_caller - .pre_block_blockhashes_contract_call(db, cfg, block_env, block.parent_hash()) + .pre_block_blockhashes_contract_call( + db, + evm_env.cfg_env_with_handler_cfg(), + evm_env.block_env(), + block.parent_hash(), + ) .map_err(|_| { EthApiError::EvmCustom("failed to apply blockhashes system call".to_string()) })?; diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index b88bac816f8bf..419cc869988e0 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -37,11 +37,12 @@ use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; use reth_tasks::pool::BlockingTaskGuard; use revm::{ db::{CacheDB, State}, - primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg}, + primitives::{db::DatabaseCommit, Env}, }; use revm_inspectors::tracing::{ FourByteInspector, MuxInspector, TracingInspector, TracingInspectorConfig, TransactionContext, }; +use revm_primitives::TxEnv; use std::sync::Arc; use tokio::sync::{AcquireError, OwnedSemaphorePermit}; @@ -95,8 +96,7 @@ where async fn trace_block( &self, block: Arc>>, - cfg: CfgEnvWithHandlerCfg, - block_env: BlockEnv, + evm_env: EvmEnv, opts: GethDebugTracingOptions, ) -> Result, Eth::Error> { // replay all transactions of the block @@ -106,24 +106,19 @@ where let mut results = Vec::with_capacity(block.body().transactions().len()); let mut db = CacheDB::new(StateProviderDatabase::new(state)); - this.eth_api().apply_pre_execution_changes(&block, &mut db, &cfg, &block_env)?; + this.eth_api().apply_pre_execution_changes(&block, &mut db, &evm_env)?; let mut transactions = block.transactions_with_sender().enumerate().peekable(); let mut inspector = None; while let Some((index, (signer, tx))) = transactions.next() { let tx_hash = *tx.tx_hash(); - let env = EnvWithHandlerCfg { - env: Env::boxed( - cfg.cfg_env.clone(), - block_env.clone(), - this.eth_api().evm_config().tx_env(tx, *signer), - ), - handler_cfg: cfg.handler_cfg, - }; + let tx_env = this.eth_api().evm_config().tx_env(tx, *signer); + let (result, state_changes) = this.trace_transaction( &opts, - env, + evm_env.clone(), + tx_env, &mut db, Some(TransactionContext { block_hash: Some(block.hash()), @@ -162,8 +157,7 @@ where .map_err(BlockError::RlpDecodeRawBlock) .map_err(Eth::Error::from_eth_err)?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = - self.eth_api().evm_config().cfg_and_block_env(block.header()); + let evm_env = self.eth_api().evm_config().cfg_and_block_env(block.header()); // Depending on EIP-2 we need to recover the transactions differently let senders = @@ -191,13 +185,8 @@ where .collect::, Eth::Error>>()? }; - self.trace_block( - Arc::new(block.with_senders_unchecked(senders).seal_slow()), - cfg_env_with_handler_cfg, - block_env, - opts, - ) - .await + self.trace_block(Arc::new(block.with_senders_unchecked(senders).seal_slow()), evm_env, opts) + .await } /// Replays a block and returns the trace of each transaction. @@ -216,11 +205,10 @@ where self.eth_api().evm_env_at(block_hash.into()), self.eth_api().block_with_senders(block_hash.into()), )?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; let block = block.ok_or(EthApiError::HeaderNotFound(block_id))?; - self.trace_block(block, cfg_env_with_handler_cfg, block_env, opts).await + self.trace_block(block, evm_env, opts).await } /// Trace the transaction according to the provided options. @@ -236,7 +224,6 @@ where Some(res) => res, }; let (evm_env, _) = self.eth_api().evm_env_at(block.hash().into()).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; // we need to get the state of the parent block because we're essentially replaying the // block the transaction is included in @@ -253,34 +240,22 @@ where let mut db = CacheDB::new(StateProviderDatabase::new(state)); - this.eth_api().apply_pre_execution_changes( - &block, - &mut db, - &cfg_env_with_handler_cfg, - &block_env, - )?; + this.eth_api().apply_pre_execution_changes(&block, &mut db, &evm_env)?; // replay all transactions prior to the targeted transaction let index = this.eth_api().replay_transactions_until( &mut db, - cfg_env_with_handler_cfg.clone(), - block_env.clone(), + evm_env.clone(), block_txs, *tx.tx_hash(), )?; - let env = EnvWithHandlerCfg { - env: Env::boxed( - cfg_env_with_handler_cfg.cfg_env.clone(), - block_env, - this.eth_api().evm_config().tx_env(tx.tx(), tx.signer()), - ), - handler_cfg: cfg_env_with_handler_cfg.handler_cfg, - }; + let tx_env = this.eth_api().evm_config().tx_env(tx.tx(), tx.signer()); this.trace_transaction( &opts, - env, + evm_env, + tx_env, &mut db, Some(TransactionContext { block_hash: Some(block_hash), @@ -319,8 +294,8 @@ where let mut inspector = FourByteInspector::default(); let inspector = self .eth_api() - .spawn_with_call_at(call, at, overrides, move |db, env| { - this.eth_api().inspect(db, env, &mut inspector)?; + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { + this.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; Ok(inspector) }) .await?; @@ -337,10 +312,11 @@ where let frame = self .eth_api() - .spawn_with_call_at(call, at, overrides, move |db, env| { - let (res, env) = this.eth_api().inspect(db, env, &mut inspector)?; + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { + let (res, (_, tx_env)) = + this.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; let frame = inspector - .with_transaction_gas_limit(env.tx.gas_limit) + .with_transaction_gas_limit(tx_env.gas_limit) .into_geth_builder() .geth_call_traces(call_config, res.result.gas_used()); Ok(frame.into()) @@ -358,15 +334,19 @@ where let frame = self .eth_api() - .spawn_with_call_at(call, at, overrides, move |db, env| { + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { // wrapper is hack to get around 'higher-ranked lifetime error', // see let db = db.0; - let (res, env) = - this.eth_api().inspect(&mut *db, env, &mut inspector)?; + let (res, (_, tx_env)) = this.eth_api().inspect( + &mut *db, + evm_env, + tx_env, + &mut inspector, + )?; let frame = inspector - .with_transaction_gas_limit(env.tx.gas_limit) + .with_transaction_gas_limit(tx_env.gas_limit) .into_geth_builder() .geth_prestate_traces(&res, &prestate_config, db) .map_err(Eth::Error::from_eth_err)?; @@ -387,25 +367,29 @@ where let frame = self .inner .eth_api - .spawn_with_call_at(call, at, overrides, move |db, env| { + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { // wrapper is hack to get around 'higher-ranked lifetime error', see // let db = db.0; let tx_info = TransactionInfo { block_number: Some( - env.block.number.try_into().unwrap_or_default(), + evm_env.block_env.number.try_into().unwrap_or_default(), ), base_fee: Some( - env.block.basefee.try_into().unwrap_or_default(), + evm_env.block_env.basefee.try_into().unwrap_or_default(), ), hash: None, block_hash: None, index: None, }; - let (res, _) = - this.eth_api().inspect(&mut *db, env, &mut inspector)?; + let (res, _) = this.eth_api().inspect( + &mut *db, + evm_env, + tx_env, + &mut inspector, + )?; let frame = inspector .try_into_mux_frame(&res, db, tx_info) .map_err(Eth::Error::from_eth_err)?; @@ -426,12 +410,12 @@ where let frame: FlatCallFrame = self .inner .eth_api - .spawn_with_call_at(call, at, overrides, move |db, env| { - let (_res, env) = - this.eth_api().inspect(db, env, &mut inspector)?; + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { + let (_res, (_, tx_env)) = + this.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; let tx_info = TransactionInfo::default(); let frame: FlatCallFrame = inspector - .with_transaction_gas_limit(env.tx.gas_limit) + .with_transaction_gas_limit(tx_env.gas_limit) .into_parity_builder() .into_localized_transaction_traces(tx_info); Ok(frame) @@ -453,7 +437,7 @@ where let res = self .eth_api() - .spawn_with_call_at(call, at, overrides, move |db, env| { + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { // wrapper is hack to get around 'higher-ranked lifetime error', see // let db = db.0; @@ -461,8 +445,17 @@ where let mut inspector = revm_inspectors::tracing::js::JsInspector::new(code, config) .map_err(Eth::Error::from_eth_err)?; - let (res, _) = - this.eth_api().inspect(&mut *db, env.clone(), &mut inspector)?; + let (res, _) = this.eth_api().inspect( + &mut *db, + evm_env.clone(), + tx_env.clone(), + &mut inspector, + )?; + let env = Env::boxed( + evm_env.cfg_env_with_handler_cfg.cfg_env, + evm_env.block_env, + tx_env, + ); inspector.json_result(res, &env, db).map_err(Eth::Error::from_eth_err) }) .await?; @@ -479,9 +472,10 @@ where let (res, tx_gas_limit, inspector) = self .eth_api() - .spawn_with_call_at(call, at, overrides, move |db, env| { - let (res, env) = this.eth_api().inspect(db, env, &mut inspector)?; - Ok((res, env.tx.gas_limit, inspector)) + .spawn_with_call_at(call, at, overrides, move |db, evm_env, tx_env| { + let (res, (_, tx_env)) = + this.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; + Ok((res, tx_env.gas_limit, inspector)) }) .await?; let gas_used = res.result.gas_used(); @@ -511,11 +505,10 @@ where let transaction_index = transaction_index.unwrap_or_default(); let target_block = block_number.unwrap_or_default(); - let ((evm_env, _), block) = futures::try_join!( + let ((mut evm_env, _), block) = futures::try_join!( self.eth_api().evm_env_at(target_block), self.eth_api().block_with_senders(target_block), )?; - let EvmEnv { cfg_env_with_handler_cfg, mut block_env } = evm_env; let opts = opts.unwrap_or_default(); let block = block.ok_or(EthApiError::HeaderNotFound(target_block))?; @@ -552,15 +545,8 @@ where // Execute all transactions until index for (signer, tx) in transactions { - let env = EnvWithHandlerCfg { - env: Env::boxed( - cfg_env_with_handler_cfg.cfg_env.clone(), - block_env.clone(), - this.eth_api().evm_config().tx_env(tx, *signer), - ), - handler_cfg: cfg_env_with_handler_cfg.handler_cfg, - }; - let (res, _) = this.eth_api().transact(&mut db, env)?; + let tx_env = this.eth_api().evm_config().tx_env(tx, *signer); + let (res, _) = this.eth_api().transact(&mut db, evm_env.clone(), tx_env)?; db.commit(res.state); } } @@ -580,9 +566,8 @@ where let state_overrides = state_overrides.take(); let overrides = EvmOverrides::new(state_overrides, block_overrides.clone()); - let env = this.eth_api().prepare_call_env( - cfg_env_with_handler_cfg.clone(), - block_env.clone(), + let (evm_env, tx_env) = this.eth_api().prepare_call_env( + evm_env.clone(), tx, &mut db, overrides, @@ -590,7 +575,8 @@ where let (trace, state) = this.trace_transaction( &tracing_options, - env, + evm_env, + tx_env, &mut db, None, &mut inspector, @@ -606,8 +592,8 @@ where results.push(trace); } // Increment block_env number and timestamp for the next bundle - block_env.number += U256::from(1); - block_env.timestamp += U256::from(12); + evm_env.block_env.number += U256::from(1); + evm_env.block_env.timestamp += U256::from(12); all_bundles.push(results); } @@ -670,7 +656,8 @@ where fn trace_transaction( &self, opts: &GethDebugTracingOptions, - env: EnvWithHandlerCfg, + evm_env: EvmEnv, + tx_env: TxEnv, db: &mut StateCacheDb<'_>, transaction_context: Option, fused_inspector: &mut Option, @@ -684,8 +671,8 @@ where .map(|c| c.tx_index.map(|i| i as u64)) .unwrap_or_default(), block_hash: transaction_context.as_ref().map(|c| c.block_hash).unwrap_or_default(), - block_number: Some(env.block.number.try_into().unwrap_or_default()), - base_fee: Some(env.block.basefee.try_into().unwrap_or_default()), + block_number: Some(evm_env.block_env.number.try_into().unwrap_or_default()), + base_fee: Some(evm_env.block_env.basefee.try_into().unwrap_or_default()), }; if let Some(tracer) = tracer { @@ -693,7 +680,8 @@ where GethDebugTracerType::BuiltInTracer(tracer) => match tracer { GethDebugBuiltInTracerType::FourByteTracer => { let mut inspector = FourByteInspector::default(); - let (res, _) = self.eth_api().inspect(db, env, &mut inspector)?; + let (res, _) = + self.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; return Ok((FourByteFrame::from(&inspector).into(), res.state)) } GethDebugBuiltInTracerType::CallTracer => { @@ -708,9 +696,10 @@ where )) }); - let (res, env) = self.eth_api().inspect(db, env, &mut inspector)?; + let (res, (_, tx_env)) = + self.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; - inspector.set_transaction_gas_limit(env.tx.gas_limit); + inspector.set_transaction_gas_limit(tx_env.gas_limit); let frame = inspector .geth_builder() @@ -729,9 +718,10 @@ where TracingInspectorConfig::from_geth_prestate_config(&prestate_config), ) }); - let (res, env) = self.eth_api().inspect(&mut *db, env, &mut inspector)?; + let (res, (_, tx_env)) = + self.eth_api().inspect(&mut *db, evm_env, tx_env, &mut inspector)?; - inspector.set_transaction_gas_limit(env.tx.gas_limit); + inspector.set_transaction_gas_limit(tx_env.gas_limit); let frame = inspector .geth_builder() .geth_prestate_traces(&res, &prestate_config, db) @@ -751,7 +741,8 @@ where let mut inspector = MuxInspector::try_from_config(mux_config) .map_err(Eth::Error::from_eth_err)?; - let (res, _) = self.eth_api().inspect(&mut *db, env, &mut inspector)?; + let (res, _) = + self.eth_api().inspect(&mut *db, evm_env, tx_env, &mut inspector)?; let frame = inspector .try_into_mux_frame(&res, db, tx_info) .map_err(Eth::Error::from_eth_err)?; @@ -767,9 +758,10 @@ where TracingInspectorConfig::from_flat_call_config(&flat_call_config), ); - let (res, env) = self.eth_api().inspect(db, env, &mut inspector)?; + let (res, (_, tx_env)) = + self.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; let frame: FlatCallFrame = inspector - .with_transaction_gas_limit(env.tx.gas_limit) + .with_transaction_gas_limit(tx_env.gas_limit) .into_parity_builder() .into_localized_transaction_traces(tx_info); @@ -790,9 +782,15 @@ where transaction_context.unwrap_or_default(), ) .map_err(Eth::Error::from_eth_err)?; - let (res, env) = self.eth_api().inspect(&mut *db, env, &mut inspector)?; + let (res, (evm_env, tx_env)) = + self.eth_api().inspect(&mut *db, evm_env, tx_env, &mut inspector)?; let state = res.state.clone(); + let env = Env::boxed( + evm_env.cfg_env_with_handler_cfg.cfg_env, + evm_env.block_env, + tx_env, + ); let result = inspector.json_result(res, &env, db).map_err(Eth::Error::from_eth_err)?; Ok((GethTrace::JS(result), state)) @@ -805,10 +803,10 @@ where let inspector_config = TracingInspectorConfig::from_geth_config(config); TracingInspector::new(inspector_config) }); - let (res, env) = self.eth_api().inspect(db, env, &mut inspector)?; + let (res, (_, tx_env)) = self.eth_api().inspect(db, evm_env, tx_env, &mut inspector)?; let gas_used = res.result.gas_used(); let return_value = res.result.into_output().unwrap_or_default(); - inspector.set_transaction_gas_limit(env.tx.gas_limit); + inspector.set_transaction_gas_limit(tx_env.gas_limit); let frame = inspector.geth_builder().geth_traces(gas_used, return_value, *config); Ok((frame.into(), res.state)) diff --git a/crates/rpc/rpc/src/eth/bundle.rs b/crates/rpc/rpc/src/eth/bundle.rs index 3cc1c1391638e..e44c5634d10bd 100644 --- a/crates/rpc/rpc/src/eth/bundle.rs +++ b/crates/rpc/rpc/src/eth/bundle.rs @@ -6,7 +6,7 @@ use alloy_primitives::{Keccak256, U256}; use alloy_rpc_types_mev::{EthCallBundle, EthCallBundleResponse, EthCallBundleTransactionResult}; use jsonrpsee::core::RpcResult; use reth_chainspec::EthChainSpec; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv}; +use reth_evm::{ConfigureEvm, ConfigureEvmEnv}; use reth_primitives_traits::SignedTransaction; use reth_provider::{ChainSpecProvider, HeaderProvider}; use reth_revm::database::StateProviderDatabase; @@ -21,9 +21,9 @@ use reth_transaction_pool::{ }; use revm::{ db::{CacheDB, DatabaseCommit, DatabaseRef}, - primitives::{ResultAndState, TxEnv}, + primitives::ResultAndState, }; -use revm_primitives::{EnvKzgSettings, EnvWithHandlerCfg, SpecId}; +use revm_primitives::{EnvKzgSettings, SpecId}; use std::sync::Arc; /// `Eth` bundle implementation. @@ -101,40 +101,40 @@ where let block_id: alloy_rpc_types_eth::BlockId = state_block_number.into(); // Note: the block number is considered the `parent` block: - let (evm_env, at) = self.eth_api().evm_env_at(block_id).await?; - let EvmEnv { cfg_env_with_handler_cfg, mut block_env } = evm_env; + let (mut evm_env, at) = self.eth_api().evm_env_at(block_id).await?; if let Some(coinbase) = coinbase { - block_env.coinbase = coinbase; + evm_env.block_env.coinbase = coinbase; } // need to adjust the timestamp for the next block if let Some(timestamp) = timestamp { - block_env.timestamp = U256::from(timestamp); + evm_env.block_env.timestamp = U256::from(timestamp); } else { - block_env.timestamp += U256::from(12); + evm_env.block_env.timestamp += U256::from(12); } if let Some(difficulty) = difficulty { - block_env.difficulty = U256::from(difficulty); + evm_env.block_env.difficulty = U256::from(difficulty); } // default to call gas limit unless user requests a smaller limit - block_env.gas_limit = U256::from(self.inner.eth_api.call_gas_limit()); + evm_env.block_env.gas_limit = U256::from(self.inner.eth_api.call_gas_limit()); if let Some(gas_limit) = gas_limit { let gas_limit = U256::from(gas_limit); - if gas_limit > block_env.gas_limit { + if gas_limit > evm_env.block_env.gas_limit { return Err( EthApiError::InvalidTransaction(RpcInvalidTransactionError::GasTooHigh).into() ) } - block_env.gas_limit = gas_limit; + evm_env.block_env.gas_limit = gas_limit; } if let Some(base_fee) = base_fee { - block_env.basefee = U256::from(base_fee); - } else if cfg_env_with_handler_cfg.handler_cfg.spec_id.is_enabled_in(SpecId::LONDON) { - let parent_block = block_env.number.saturating_to::(); + evm_env.block_env.basefee = U256::from(base_fee); + } else if evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id.is_enabled_in(SpecId::LONDON) + { + let parent_block = evm_env.block_env.number.saturating_to::(); // here we need to fetch the _next_ block's basefee based on the parent block let parent = RpcNodeCore::provider(self.eth_api()) .header_by_number(parent_block) @@ -145,25 +145,20 @@ where .chain_spec() .base_fee_params_at_block(parent_block), ) { - block_env.basefee = U256::from(base_fee); + evm_env.block_env.basefee = U256::from(base_fee); } } - let state_block_number = block_env.number; + let state_block_number = evm_env.block_env.number; // use the block number of the request - block_env.number = U256::from(block_number); + evm_env.block_env.number = U256::from(block_number); let eth_api = self.eth_api().clone(); self.eth_api() .spawn_with_state_at_block(at, move |state| { - let coinbase = block_env.coinbase; - let basefee = Some(block_env.basefee.to::()); - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg, - block_env, - TxEnv::default(), - ); + let coinbase = evm_env.block_env.coinbase; + let basefee = Some(evm_env.block_env.basefee.to::()); let db = CacheDB::new(StateProviderDatabase::new(state)); let initial_coinbase = db @@ -177,7 +172,7 @@ where let mut total_gas_fess = U256::ZERO; let mut hasher = Keccak256::new(); - let mut evm = eth_api.evm_config().evm_with_env(db, env); + let mut evm = eth_api.evm_config().evm_with_env(db, evm_env, Default::default()); let mut results = Vec::with_capacity(transactions.len()); let mut transactions = transactions.into_iter().peekable(); diff --git a/crates/rpc/rpc/src/eth/sim_bundle.rs b/crates/rpc/rpc/src/eth/sim_bundle.rs index de2597b64a3fd..1c24a5f4a4b8e 100644 --- a/crates/rpc/rpc/src/eth/sim_bundle.rs +++ b/crates/rpc/rpc/src/eth/sim_bundle.rs @@ -10,7 +10,7 @@ use alloy_rpc_types_mev::{ }; use jsonrpsee::core::RpcResult; use reth_chainspec::EthChainSpec; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv}; +use reth_evm::{ConfigureEvm, ConfigureEvmEnv}; use reth_provider::{ChainSpecProvider, HeaderProvider, ProviderTx}; use reth_revm::database::StateProviderDatabase; use reth_rpc_api::MevSimApiServer; @@ -23,7 +23,7 @@ use reth_tasks::pool::BlockingTaskGuard; use reth_transaction_pool::{PoolConsensusTx, PoolPooledTx, PoolTransaction, TransactionPool}; use revm::{ db::CacheDB, - primitives::{Address, EnvWithHandlerCfg, ResultAndState, SpecId, TxEnv}, + primitives::{Address, ResultAndState, SpecId}, DatabaseCommit, DatabaseRef, }; use std::{sync::Arc, time::Duration}; @@ -244,42 +244,44 @@ where let flattened_bundle = self.parse_and_flatten_bundle(&request)?; let block_id = parent_block.unwrap_or(BlockId::Number(BlockNumberOrTag::Pending)); - let (evm_env, current_block) = self.eth_api().evm_env_at(block_id).await?; - let EvmEnv { cfg_env_with_handler_cfg, mut block_env } = evm_env; + let (mut evm_env, current_block) = self.eth_api().evm_env_at(block_id).await?; let parent_header = RpcNodeCore::provider(&self.inner.eth_api) - .header_by_number(block_env.number.saturating_to::()) + .header_by_number(evm_env.block_env.number.saturating_to::()) .map_err(EthApiError::from_eth_err)? // Explicitly map the error .ok_or_else(|| { - EthApiError::HeaderNotFound((block_env.number.saturating_to::()).into()) + EthApiError::HeaderNotFound( + (evm_env.block_env.number.saturating_to::()).into(), + ) })?; // apply overrides if let Some(block_number) = block_number { - block_env.number = U256::from(block_number); + evm_env.block_env.number = U256::from(block_number); } if let Some(coinbase) = coinbase { - block_env.coinbase = coinbase; + evm_env.block_env.coinbase = coinbase; } if let Some(timestamp) = timestamp { - block_env.timestamp = U256::from(timestamp); + evm_env.block_env.timestamp = U256::from(timestamp); } if let Some(gas_limit) = gas_limit { - block_env.gas_limit = U256::from(gas_limit); + evm_env.block_env.gas_limit = U256::from(gas_limit); } if let Some(base_fee) = base_fee { - block_env.basefee = U256::from(base_fee); - } else if cfg_env_with_handler_cfg.handler_cfg.spec_id.is_enabled_in(SpecId::LONDON) { + evm_env.block_env.basefee = U256::from(base_fee); + } else if evm_env.cfg_env_with_handler_cfg.handler_cfg.spec_id.is_enabled_in(SpecId::LONDON) + { if let Some(base_fee) = parent_header.next_block_base_fee( RpcNodeCore::provider(&self.inner.eth_api) .chain_spec() - .base_fee_params_at_block(block_env.number.saturating_to::()), + .base_fee_params_at_block(evm_env.block_env.number.saturating_to::()), ) { - block_env.basefee = U256::from(base_fee); + evm_env.block_env.basefee = U256::from(base_fee); } } @@ -291,13 +293,8 @@ where .spawn_with_state_at_block(current_block, move |state| { // Setup environment let current_block_number = current_block.as_u64().unwrap(); - let coinbase = block_env.coinbase; - let basefee = block_env.basefee; - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg, - block_env, - TxEnv::default(), - ); + let coinbase = evm_env.block_env.coinbase; + let basefee = evm_env.block_env.basefee; let db = CacheDB::new(StateProviderDatabase::new(state)); let initial_coinbase_balance = DatabaseRef::basic_ref(&db, coinbase) @@ -311,7 +308,7 @@ where let mut refundable_value = U256::ZERO; let mut body_logs: Vec = Vec::new(); - let mut evm = eth_api.evm_config().evm_with_env(db, env); + let mut evm = eth_api.evm_config().evm_with_env(db, evm_env, Default::default()); for item in &flattened_bundle { // Check inclusion constraints diff --git a/crates/rpc/rpc/src/trace.rs b/crates/rpc/rpc/src/trace.rs index d906419021b90..b7bf38eb608d6 100644 --- a/crates/rpc/rpc/src/trace.rs +++ b/crates/rpc/rpc/src/trace.rs @@ -16,7 +16,7 @@ use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_chainspec::{EthChainSpec, EthereumHardfork, MAINNET, SEPOLIA}; use reth_consensus_common::calc::{base_block_reward_pre_merge, block_reward, ommer_reward}; -use reth_evm::{env::EvmEnv, ConfigureEvmEnv}; +use reth_evm::ConfigureEvmEnv; use reth_primitives_traits::{BlockBody, BlockHeader}; use reth_provider::{BlockNumReader, BlockReader, ChainSpecProvider}; use reth_revm::database::StateProviderDatabase; @@ -25,10 +25,7 @@ use reth_rpc_eth_api::{helpers::TraceExt, FromEthApiError, RpcNodeCore}; use reth_rpc_eth_types::{error::EthApiError, utils::recover_raw_transaction}; use reth_tasks::pool::BlockingTaskGuard; use reth_transaction_pool::{PoolPooledTx, PoolTransaction, TransactionPool}; -use revm::{ - db::{CacheDB, DatabaseCommit}, - primitives::EnvWithHandlerCfg, -}; +use revm::db::{CacheDB, DatabaseCommit}; use revm_inspectors::{ opcode::OpcodeGasInspector, tracing::{parity::populate_state_diff, TracingInspector, TracingInspectorConfig}, @@ -90,12 +87,12 @@ where let mut inspector = TracingInspector::new(config); let this = self.clone(); self.eth_api() - .spawn_with_call_at(trace_request.call, at, overrides, move |db, env| { + .spawn_with_call_at(trace_request.call, at, overrides, move |db, evm_env, tx_env| { // wrapper is hack to get around 'higher-ranked lifetime error', see // let db = db.0; - let (res, _) = this.eth_api().inspect(&mut *db, env, &mut inspector)?; + let (res, _) = this.eth_api().inspect(&mut *db, evm_env, tx_env, &mut inspector)?; let trace_res = inspector .into_parity_builder() .into_trace_results_with_state(&res, &trace_request.trace_types, &db) @@ -116,18 +113,12 @@ where .map_transaction(::Transaction::pooled_into_consensus); let (evm_env, at) = self.eth_api().evm_env_at(block_id.unwrap_or_default()).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; - - let env = EnvWithHandlerCfg::new_with_cfg_env( - cfg_env_with_handler_cfg, - block_env, - self.eth_api().evm_config().tx_env(tx.tx(), tx.signer()), - ); + let tx_env = self.eth_api().evm_config().tx_env(tx.tx(), tx.signer()); let config = TracingInspectorConfig::from_parity_config(&trace_types); self.eth_api() - .spawn_trace_at_with_state(env, config, at, move |inspector, res, db| { + .spawn_trace_at_with_state(evm_env, tx_env, config, at, move |inspector, res, db| { inspector .into_parity_builder() .into_trace_results_with_state(&res, &trace_types, &db) @@ -147,7 +138,6 @@ where ) -> Result, Eth::Error> { let at = block_id.unwrap_or(BlockId::pending()); let (evm_env, at) = self.eth_api().evm_env_at(at).await?; - let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env; let this = self.clone(); // execute all transactions on top of each other and record the traces @@ -159,16 +149,16 @@ where let mut calls = calls.into_iter().peekable(); while let Some((call, trace_types)) = calls.next() { - let env = this.eth_api().prepare_call_env( - cfg_env_with_handler_cfg.clone(), - block_env.clone(), + let (evm_env, tx_env) = this.eth_api().prepare_call_env( + evm_env.clone(), call, &mut db, Default::default(), )?; let config = TracingInspectorConfig::from_parity_config(&trace_types); let mut inspector = TracingInspector::new(config); - let (res, _) = this.eth_api().inspect(&mut db, env, &mut inspector)?; + let (res, _) = + this.eth_api().inspect(&mut db, evm_env, tx_env, &mut inspector)?; let trace_res = inspector .into_parity_builder() diff --git a/examples/custom-inspector/Cargo.toml b/examples/custom-inspector/Cargo.toml index ee6f887e64c0d..5d9753da7253a 100644 --- a/examples/custom-inspector/Cargo.toml +++ b/examples/custom-inspector/Cargo.toml @@ -7,7 +7,9 @@ license.workspace = true [dependencies] reth.workspace = true +reth-evm.workspace = true reth-node-ethereum.workspace = true +revm-primitives.workspace = true alloy-rpc-types-eth.workspace = true clap = { workspace = true, features = ["derive"] } futures-util.workspace = true diff --git a/examples/custom-inspector/src/main.rs b/examples/custom-inspector/src/main.rs index 6b25c46b76ca3..5df076008bdd1 100644 --- a/examples/custom-inspector/src/main.rs +++ b/examples/custom-inspector/src/main.rs @@ -22,12 +22,15 @@ use reth::{ revm::{ inspector_handle_register, interpreter::{Interpreter, OpCode}, + primitives::{Env, EnvWithHandlerCfg}, Database, Evm, EvmContext, Inspector, }, rpc::{api::eth::helpers::Call, compat::transaction::transaction_to_call_request}, transaction_pool::TransactionPool, }; +use reth_evm::EvmEnv; use reth_node_ethereum::node::EthereumNode; +use revm_primitives::CfgEnvWithHandlerCfg; fn main() { Cli::::parse() @@ -61,7 +64,16 @@ fn main() { call_request, BlockNumberOrTag::Latest.into(), EvmOverrides::default(), - move |db, env| { + move |db, evm_env, tx_env| { + let EvmEnv { + cfg_env_with_handler_cfg: + CfgEnvWithHandlerCfg { handler_cfg, cfg_env }, + block_env, + } = evm_env; + let env = EnvWithHandlerCfg { + handler_cfg, + env: Env::boxed(cfg_env, block_env, tx_env), + }; let mut dummy_inspector = DummyInspector::default(); { // configure the evm with the custom inspector