diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 55509fd17..b290a10e2 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -702,7 +702,8 @@ mod tests { let chain_spec = Arc::new( ChainSpecBuilder::from(&*MAINNET) .shanghai_activated() - .with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0)) + .cancun_activated() + .prague_activated() .build(), ); @@ -740,6 +741,7 @@ mod tests { let chain_spec = Arc::new( ChainSpecBuilder::from(&*MAINNET) .shanghai_activated() + .cancun_activated() .with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(1)) .build(), ); @@ -749,6 +751,8 @@ mod tests { timestamp: 1, number: fork_activation_block, requests_hash: Some(EMPTY_REQUESTS_HASH), + excess_blob_gas: Some(0), + parent_beacon_block_root: Some(B256::random()), ..Header::default() }; let provider = executor_provider(chain_spec); @@ -790,6 +794,7 @@ mod tests { let chain_spec = Arc::new( ChainSpecBuilder::from(&*MAINNET) .shanghai_activated() + .cancun_activated() .with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(1)) .build(), ); @@ -802,6 +807,8 @@ mod tests { timestamp: 1, number: fork_activation_block, requests_hash: Some(EMPTY_REQUESTS_HASH), + excess_blob_gas: Some(0), + parent_beacon_block_root: Some(B256::random()), ..Header::default() }; @@ -827,12 +834,12 @@ mod tests { let chain_spec = Arc::new( ChainSpecBuilder::from(&*MAINNET) .shanghai_activated() - .with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0)) + .cancun_activated() + .prague_activated() .build(), ); - let mut header = chain_spec.genesis_header().clone(); - header.requests_hash = Some(EMPTY_REQUESTS_HASH); + let header = chain_spec.genesis_header().clone(); let header_hash = header.hash_slow(); let provider = executor_provider(chain_spec); @@ -864,6 +871,8 @@ mod tests { timestamp: 1, number: 1, requests_hash: Some(EMPTY_REQUESTS_HASH), + excess_blob_gas: Some(0), + parent_beacon_block_root: Some(B256::random()), ..Header::default() }; let header_hash = header.hash_slow(); @@ -897,6 +906,8 @@ mod tests { timestamp: 1, number: 2, requests_hash: Some(EMPTY_REQUESTS_HASH), + excess_blob_gas: Some(0), + parent_beacon_block_root: Some(B256::random()), ..Header::default() }; @@ -935,7 +946,8 @@ mod tests { let chain_spec = Arc::new( ChainSpecBuilder::from(&*MAINNET) .shanghai_activated() - .with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0)) + .cancun_activated() + .prague_activated() .build(), ); @@ -1084,7 +1096,8 @@ mod tests { let chain_spec = Arc::new( ChainSpecBuilder::from(&*MAINNET) .shanghai_activated() - .with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0)) + .cancun_activated() + .prague_activated() .build(), ); @@ -1102,7 +1115,13 @@ mod tests { let withdrawal = Withdrawal { index: 0, validator_index: 0, address: withdrawal_recipient, amount: 1 }; - let header = Header { timestamp: 1, number: 1, ..Header::default() }; + let header = Header { + timestamp: 1, + number: 1, + excess_blob_gas: Some(0), + parent_beacon_block_root: Some(B256::random()), + ..Header::default() + }; let block = &RecoveredBlock::new_unhashed( Block { diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index 2f26cbc80..aa8cf3d06 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -28,7 +28,7 @@ use reth_primitives_traits::transaction::execute::FillTxEnv; use reth_revm::{inspector_handle_register, Database, EvmBuilder}; use revm_primitives::{ AnalysisKind, BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv, CfgEnvWithHandlerCfg, EVMError, - Env, ResultAndState, SpecId, TxEnv, TxKind, + Env, HandlerCfg, ResultAndState, SpecId, TxEnv, TxKind, }; mod config; @@ -152,20 +152,43 @@ impl ConfigureEvmEnv for EthEvmConfig { type Error = Infallible; type TxEnv = TxEnv; - fn fill_tx_env(&self, tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address) { - transaction.fill_tx_env(tx_env, sender); + fn tx_env(&self, transaction: &TransactionSigned, sender: Address) -> Self::TxEnv { + let mut tx_env = TxEnv::default(); + transaction.fill_tx_env(&mut tx_env, sender); + tx_env } - fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Header) { + fn evm_env(&self, header: &Self::Header) -> EvmEnv { let spec_id = config::revm_spec(self.chain_spec(), header); + let mut cfg_env = CfgEnv::default(); cfg_env.chain_id = self.chain_spec.chain().id(); - cfg_env.perf_analyse_created_bytecodes = AnalysisKind::Analyse; + cfg_env.perf_analyse_created_bytecodes = AnalysisKind::default(); - cfg_env.handler_cfg.spec_id = spec_id; + let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { + cfg_env, + #[allow(clippy::needless_update)] // side-effect of optimism fields + handler_cfg: HandlerCfg { spec_id, ..Default::default() }, + }; + + let block_env = BlockEnv { + number: U256::from(header.number()), + coinbase: header.beneficiary(), + timestamp: U256::from(header.timestamp()), + difficulty: if spec_id >= SpecId::MERGE { U256::ZERO } else { header.difficulty() }, + prevrandao: if spec_id >= SpecId::MERGE { header.mix_hash() } else { None }, + gas_limit: U256::from(header.gas_limit()), + basefee: U256::from(header.base_fee_per_gas().unwrap_or_default()), + // EIP-4844 excess blob gas of this block, introduced in Cancun + blob_excess_gas_and_price: header.excess_blob_gas.map(|excess_blob_gas| { + BlobExcessGasAndPrice::new(excess_blob_gas, spec_id >= SpecId::PRAGUE) + }), + }; + + EvmEnv { cfg_env_with_handler_cfg, block_env } } - fn next_cfg_and_block_env( + fn next_evm_env( &self, parent: &Self::Header, attributes: NextBlockEnvAttributes, @@ -296,7 +319,7 @@ mod tests { // Use the `EthEvmConfig` to fill the `cfg_env` and `block_env` based on the ChainSpec, // Header, and total difficulty let EvmEnv { cfg_env_with_handler_cfg, .. } = - EthEvmConfig::new(Arc::new(chain_spec.clone())).cfg_and_block_env(&header); + EthEvmConfig::new(Arc::new(chain_spec.clone())).evm_env(&header); // Assert that the chain ID in the `cfg_env` is correctly set to the chain ID of the // ChainSpec diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index b4f313aa4..6cfc2a023 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -92,7 +92,7 @@ where prev_randao: config.attributes.prev_randao(), gas_limit: self.builder_config.gas_limit(parent.gas_limit), }; - self.evm_config.next_cfg_and_block_env(parent, next_attributes) + self.evm_config.next_evm_env(parent, next_attributes) } } diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index 22c7f1675..a76008d9a 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -19,14 +19,11 @@ extern crate alloc; use core::fmt::Debug; -use alloy_consensus::BlockHeader as _; use alloy_eips::eip2930::AccessList; use alloy_primitives::{Address, Bytes, B256, U256}; use reth_primitives_traits::{BlockHeader, SignedTransaction}; use revm::{Database, DatabaseCommit, GetInspector}; -use revm_primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, EVMError, ResultAndState, SpecId, TxEnv, TxKind, -}; +use revm_primitives::{BlockEnv, EVMError, ResultAndState, TxEnv, TxKind}; pub mod either; /// EVM environment configuration. @@ -106,13 +103,13 @@ pub trait ConfigureEvm: ConfigureEvmEnv { /// Returns a new EVM with the given database configured with `cfg` and `block_env` /// configuration derived from the given header. Relies on - /// [`ConfigureEvmEnv::cfg_and_block_env`]. + /// [`ConfigureEvmEnv::evm_env`]. /// /// # Caution /// /// This does not initialize the tx environment. fn evm_for_block(&self, db: DB, header: &Self::Header) -> Self::Evm<'_, DB, ()> { - let evm_env = self.cfg_and_block_env(header); + let evm_env = self.evm_env(header); self.evm_with_env(db, evm_env) } @@ -177,86 +174,21 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static { /// Transaction environment used by EVM. type TxEnv: TransactionEnv; - /// The error type that is returned by [`Self::next_cfg_and_block_env`]. + /// The error type that is returned by [`Self::next_evm_env`]. type Error: core::error::Error + Send + Sync; /// Returns a [`TxEnv`] from a transaction and [`Address`]. - fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { - let mut tx_env = Default::default(); - self.fill_tx_env(&mut tx_env, transaction, signer); - tx_env - } - - /// Fill transaction environment from a transaction and the given sender address. - fn fill_tx_env( - &self, - tx_env: &mut Self::TxEnv, - transaction: &Self::Transaction, - sender: Address, - ); - - /// Returns a [`CfgEnvWithHandlerCfg`] for the given header. - fn cfg_env(&self, header: &Self::Header) -> CfgEnvWithHandlerCfg { - let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default()); - self.fill_cfg_env(&mut cfg, header); - cfg - } - - /// Fill [`CfgEnvWithHandlerCfg`] fields according to the chain spec and given header. - /// - /// This __must__ set the corresponding spec id in the handler cfg, based on timestamp or total - /// difficulty - fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header); - - /// Fill [`BlockEnv`] field according to the chain spec and given header - fn fill_block_env(&self, block_env: &mut BlockEnv, header: &Self::Header, spec_id: SpecId) { - block_env.number = U256::from(header.number()); - block_env.coinbase = header.beneficiary(); - block_env.timestamp = U256::from(header.timestamp()); - if spec_id >= SpecId::MERGE { - block_env.prevrandao = header.mix_hash(); - block_env.difficulty = U256::ZERO; - } else { - block_env.difficulty = header.difficulty(); - block_env.prevrandao = None; - } - block_env.basefee = U256::from(header.base_fee_per_gas().unwrap_or_default()); - block_env.gas_limit = U256::from(header.gas_limit()); - - // EIP-4844 excess blob gas of this block, introduced in Cancun - if let Some(excess_blob_gas) = header.excess_blob_gas() { - block_env.set_blob_excess_gas_and_price(excess_blob_gas, spec_id >= SpecId::PRAGUE); - } - } + fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv; /// Creates a new [`EvmEnv`] for the given header. - fn cfg_and_block_env(&self, header: &Self::Header) -> EvmEnv { - let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default()); - let mut block_env = BlockEnv::default(); - self.fill_cfg_and_block_env(&mut cfg, &mut block_env, header); - EvmEnv::new(cfg, block_env) - } - - /// Convenience function to call both [`fill_cfg_env`](ConfigureEvmEnv::fill_cfg_env) and - /// [`ConfigureEvmEnv::fill_block_env`]. - /// - /// Note: Implementers should ensure that all fields are required fields are filled. - fn fill_cfg_and_block_env( - &self, - cfg: &mut CfgEnvWithHandlerCfg, - block_env: &mut BlockEnv, - header: &Self::Header, - ) { - self.fill_cfg_env(cfg, header); - self.fill_block_env(block_env, header, cfg.handler_cfg.spec_id); - } + fn evm_env(&self, header: &Self::Header) -> EvmEnv; /// Returns the configured [`EvmEnv`] for `parent + 1` block. /// /// This is intended for usage in block building after the merge and requires additional /// attributes that can't be derived from the parent block: attributes that are determined by /// the CL, such as the timestamp, suggested fee recipient, and randomness value. - fn next_cfg_and_block_env( + fn next_evm_env( &self, parent: &Self::Header, attributes: NextBlockEnvAttributes, @@ -265,7 +197,7 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static { /// Represents additional attributes required to configure the next block. /// This is used to configure the next block's environment -/// [`ConfigureEvmEnv::next_cfg_and_block_env`] and contains fields that can't be derived from the +/// [`ConfigureEvmEnv::next_evm_env`] and contains fields that can't be derived from the /// parent header alone (attributes that are determined by the CL.) #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct NextBlockEnvAttributes { diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index a5c4d9640..80ca0464f 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -13,7 +13,7 @@ extern crate alloc; use alloc::sync::Arc; -use alloy_consensus::Header; +use alloy_consensus::{BlockHeader, Header}; use alloy_eips::eip7840::BlobParams; use alloy_primitives::{Address, U256}; use core::fmt::Debug; @@ -159,21 +159,42 @@ impl ConfigureEvmEnv for OpEvmConfig { type Error = EIP1559ParamError; type TxEnv = TxEnv; - fn fill_tx_env(&self, tx_env: &mut TxEnv, transaction: &OpTransactionSigned, sender: Address) { - transaction.fill_tx_env(tx_env, sender); + fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { + let mut tx_env = TxEnv::default(); + transaction.fill_tx_env(&mut tx_env, signer); + tx_env } - fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header) { - let spec_id = revm_spec(self.chain_spec(), header); + fn evm_env(&self, header: &Self::Header) -> EvmEnv { + let spec_id = config::revm_spec(self.chain_spec(), header); + let mut cfg_env = CfgEnv::default(); cfg_env.chain_id = self.chain_spec.chain().id(); - cfg_env.perf_analyse_created_bytecodes = AnalysisKind::Analyse; + cfg_env.perf_analyse_created_bytecodes = AnalysisKind::default(); - cfg_env.handler_cfg.spec_id = spec_id; - cfg_env.handler_cfg.is_optimism = true; + let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { + cfg_env, + handler_cfg: HandlerCfg { spec_id, is_optimism: true }, + }; + + let block_env = BlockEnv { + number: U256::from(header.number()), + coinbase: header.beneficiary(), + timestamp: U256::from(header.timestamp()), + difficulty: if spec_id >= SpecId::MERGE { U256::ZERO } else { header.difficulty() }, + prevrandao: if spec_id >= SpecId::MERGE { header.mix_hash() } else { None }, + gas_limit: U256::from(header.gas_limit()), + basefee: U256::from(header.base_fee_per_gas().unwrap_or_default()), + // EIP-4844 excess blob gas of this block, introduced in Cancun + blob_excess_gas_and_price: header.excess_blob_gas().map(|excess_blob_gas| { + BlobExcessGasAndPrice::new(excess_blob_gas, spec_id >= SpecId::PRAGUE) + }), + }; + + EvmEnv { cfg_env_with_handler_cfg, block_env } } - fn next_cfg_and_block_env( + fn next_evm_env( &self, parent: &Self::Header, attributes: NextBlockEnvAttributes, @@ -298,8 +319,7 @@ mod tests { // Use the `OpEvmConfig` to create the `cfg_env` and `block_env` based on the ChainSpec, // Header, and total difficulty let EvmEnv { cfg_env_with_handler_cfg, .. } = - OpEvmConfig::new(Arc::new(OpChainSpec { inner: chain_spec.clone() })) - .cfg_and_block_env(&header); + OpEvmConfig::new(Arc::new(OpChainSpec { inner: chain_spec.clone() })).evm_env(&header); // Assert that the chain ID in the `cfg_env` is correctly set to the chain ID of the // ChainSpec diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 18d4b552e..36a8ca9b9 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -173,7 +173,7 @@ where prev_randao: attributes.prev_randao(), gas_limit: attributes.gas_limit.unwrap_or(parent.gas_limit), }; - self.evm_config.next_cfg_and_block_env(parent, next_attributes) + self.evm_config.next_evm_env(parent, next_attributes) } /// Computes the witness for the payload. diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 8f10dc0f6..f3e72e908 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -83,7 +83,7 @@ pub trait LoadPendingBlock: // Note: for the PENDING block we assume it is past the known merge block and // thus this will not fail when looking up the total // difficulty value for the blockenv. - let evm_env = self.evm_config().cfg_and_block_env(block.header()); + let evm_env = self.evm_config().evm_env(block.header()); return Ok(PendingBlockEnv::new( evm_env, @@ -102,7 +102,7 @@ pub trait LoadPendingBlock: let evm_env = self .evm_config() - .next_cfg_and_block_env( + .next_evm_env( &latest, NextBlockEnvAttributes { timestamp: latest.timestamp() + 12, diff --git a/crates/rpc/rpc-eth-api/src/helpers/state.rs b/crates/rpc/rpc-eth-api/src/helpers/state.rs index 2f33ab112..c83814e47 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/state.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/state.rs @@ -230,7 +230,7 @@ pub trait LoadState: let header = self.cache().get_header(block_hash).await.map_err(Self::Error::from_eth_err)?; - let evm_env = self.evm_config().cfg_and_block_env(&header); + let evm_env = self.evm_config().evm_env(&header); Ok((evm_env, block_hash.into())) } diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 37a96356f..1969a08b4 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -156,7 +156,7 @@ where .map_err(BlockError::RlpDecodeRawBlock) .map_err(Eth::Error::from_eth_err)?; - let evm_env = self.eth_api().evm_config().cfg_and_block_env(block.header()); + let evm_env = self.eth_api().evm_config().evm_env(block.header()); // Depending on EIP-2 we need to recover the transactions differently let senders = diff --git a/examples/custom-evm/src/main.rs b/examples/custom-evm/src/main.rs index cc28270fc..5b2fe3372 100644 --- a/examples/custom-evm/src/main.rs +++ b/examples/custom-evm/src/main.rs @@ -15,7 +15,7 @@ use reth::{ handler::register::EvmHandler, inspector_handle_register, precompile::{Precompile, PrecompileOutput, PrecompileSpecId}, - primitives::{CfgEnvWithHandlerCfg, Env, PrecompileResult, TxEnv}, + primitives::{Env, PrecompileResult, TxEnv}, ContextPrecompiles, Database, EvmBuilder, GetInspector, }, rpc::types::engine::PayloadAttributes, @@ -89,20 +89,20 @@ impl ConfigureEvmEnv for MyEvmConfig { type Error = Infallible; type TxEnv = TxEnv; - fn fill_tx_env(&self, tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address) { - self.inner.fill_tx_env(tx_env, transaction, sender); + fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { + self.inner.tx_env(transaction, signer) } - fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header) { - self.inner.fill_cfg_env(cfg_env, header); + fn evm_env(&self, header: &Self::Header) -> EvmEnv { + self.inner.evm_env(header) } - fn next_cfg_and_block_env( + fn next_evm_env( &self, parent: &Self::Header, attributes: NextBlockEnvAttributes, ) -> Result { - self.inner.next_cfg_and_block_env(parent, attributes) + self.inner.next_evm_env(parent, attributes) } } diff --git a/examples/stateful-precompile/src/main.rs b/examples/stateful-precompile/src/main.rs index 69d816bb5..3e4211f24 100644 --- a/examples/stateful-precompile/src/main.rs +++ b/examples/stateful-precompile/src/main.rs @@ -13,9 +13,7 @@ use reth::{ handler::register::EvmHandler, inspector_handle_register, precompile::{Precompile, PrecompileSpecId}, - primitives::{ - CfgEnvWithHandlerCfg, Env, PrecompileResult, SpecId, StatefulPrecompileMut, TxEnv, - }, + primitives::{Env, PrecompileResult, SpecId, StatefulPrecompileMut, TxEnv}, ContextPrecompile, ContextPrecompiles, Database, EvmBuilder, GetInspector, }, tasks::TaskManager, @@ -152,20 +150,20 @@ impl ConfigureEvmEnv for MyEvmConfig { type Error = Infallible; type TxEnv = TxEnv; - fn fill_tx_env(&self, tx_env: &mut TxEnv, transaction: &TransactionSigned, sender: Address) { - self.inner.fill_tx_env(tx_env, transaction, sender) + fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { + self.inner.tx_env(transaction, signer) } - fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header) { - self.inner.fill_cfg_env(cfg_env, header) + fn evm_env(&self, header: &Self::Header) -> EvmEnv { + self.inner.evm_env(header) } - fn next_cfg_and_block_env( + fn next_evm_env( &self, parent: &Self::Header, attributes: NextBlockEnvAttributes, ) -> Result { - self.inner.next_cfg_and_block_env(parent, attributes) + self.inner.next_evm_env(parent, attributes) } }