refactor: always create Evm through ConfigureEvm (#13812)

This commit is contained in:
Arsenii Kulikov
2025-01-16 15:40:45 +04:00
committed by GitHub
parent f1f9d5a652
commit 265f783c22
9 changed files with 49 additions and 100 deletions

1
Cargo.lock generated
View File

@ -9004,6 +9004,7 @@ dependencies = [
"reth-chain-state", "reth-chain-state",
"reth-chainspec", "reth-chainspec",
"reth-errors", "reth-errors",
"reth-evm",
"reth-execution-types", "reth-execution-types",
"reth-metrics", "reth-metrics",
"reth-primitives", "reth-primitives",

View File

@ -202,12 +202,7 @@ where
// apply eip-4788 pre block contract call // apply eip-4788 pre block contract call
system_caller system_caller
.pre_block_beacon_root_contract_call( .pre_block_beacon_root_contract_call(&mut db, &evm_env, attributes.parent_beacon_block_root)
&mut db,
evm_env.cfg_env_with_handler_cfg(),
evm_env.block_env(),
attributes.parent_beacon_block_root,
)
.map_err(|err| { .map_err(|err| {
warn!(target: "payload_builder", warn!(target: "payload_builder",
parent_hash=%parent_header.hash(), parent_hash=%parent_header.hash(),
@ -220,8 +215,7 @@ where
// apply eip-2935 blockhashes update // apply eip-2935 blockhashes update
system_caller.pre_block_blockhashes_contract_call( system_caller.pre_block_blockhashes_contract_call(
&mut db, &mut db,
evm_env.cfg_env_with_handler_cfg(), &evm_env,
evm_env.block_env(),
parent_header.hash(), parent_header.hash(),
) )
.map_err(|err| { .map_err(|err| {

View File

@ -1,6 +1,6 @@
//! System contract call functions. //! System contract call functions.
use crate::ConfigureEvm; use crate::{ConfigureEvm, EvmEnv};
use alloc::{boxed::Box, sync::Arc}; use alloc::{boxed::Box, sync::Arc};
use alloy_consensus::BlockHeader; use alloy_consensus::BlockHeader;
use alloy_eips::{ use alloy_eips::{
@ -11,7 +11,7 @@ use core::fmt::Display;
use reth_chainspec::EthereumHardforks; use reth_chainspec::EthereumHardforks;
use reth_execution_errors::BlockExecutionError; use reth_execution_errors::BlockExecutionError;
use revm::{Database, DatabaseCommit, Evm}; use revm::{Database, DatabaseCommit, Evm};
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, EvmState, B256}; use revm_primitives::{EvmState, B256};
mod eip2935; mod eip2935;
mod eip4788; mod eip4788;
@ -70,24 +70,6 @@ impl<EvmConfig, Chainspec> SystemCaller<EvmConfig, Chainspec> {
pub fn finish(self) {} pub fn finish(self) {}
} }
fn initialize_evm<'a, DB>(
db: &'a mut DB,
initialized_cfg: &'a CfgEnvWithHandlerCfg,
initialized_block_env: &'a BlockEnv,
) -> Evm<'a, (), &'a mut DB>
where
DB: Database,
{
Evm::builder()
.with_db(db)
.with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env(
initialized_cfg.clone(),
initialized_block_env.clone(),
Default::default(),
))
.build()
}
impl<EvmConfig, Chainspec> SystemCaller<EvmConfig, Chainspec> impl<EvmConfig, Chainspec> SystemCaller<EvmConfig, Chainspec>
where where
EvmConfig: ConfigureEvm, EvmConfig: ConfigureEvm,
@ -149,18 +131,19 @@ where
pub fn pre_block_blockhashes_contract_call<DB>( pub fn pre_block_blockhashes_contract_call<DB>(
&mut self, &mut self,
db: &mut DB, db: &mut DB,
initialized_cfg: &CfgEnvWithHandlerCfg, evm_env: &EvmEnv,
initialized_block_env: &BlockEnv,
parent_block_hash: B256, parent_block_hash: B256,
) -> Result<(), BlockExecutionError> ) -> Result<(), BlockExecutionError>
where where
DB: Database + DatabaseCommit, DB: Database + DatabaseCommit,
DB::Error: Display, DB::Error: Display,
{ {
let mut evm = initialize_evm(db, initialized_cfg, initialized_block_env); let evm_config = self.evm_config.clone();
let mut evm = evm_config.evm_with_env(db, evm_env.clone(), Default::default());
self.apply_blockhashes_contract_call( self.apply_blockhashes_contract_call(
initialized_block_env.timestamp.to(), evm_env.block_env.timestamp.to(),
initialized_block_env.number.to(), evm_env.block_env.number.to(),
parent_block_hash, parent_block_hash,
&mut evm, &mut evm,
)?; )?;
@ -203,19 +186,19 @@ where
pub fn pre_block_beacon_root_contract_call<DB>( pub fn pre_block_beacon_root_contract_call<DB>(
&mut self, &mut self,
db: &mut DB, db: &mut DB,
initialized_cfg: &CfgEnvWithHandlerCfg, evm_env: &EvmEnv,
initialized_block_env: &BlockEnv,
parent_beacon_block_root: Option<B256>, parent_beacon_block_root: Option<B256>,
) -> Result<(), BlockExecutionError> ) -> Result<(), BlockExecutionError>
where where
DB: Database + DatabaseCommit, DB: Database + DatabaseCommit,
DB::Error: Display, DB::Error: Display,
{ {
let mut evm = initialize_evm(db, initialized_cfg, initialized_block_env); let evm_config = self.evm_config.clone();
let mut evm = evm_config.evm_with_env(db, evm_env.clone(), Default::default());
self.apply_beacon_root_contract_call( self.apply_beacon_root_contract_call(
initialized_block_env.timestamp.to(), evm_env.block_env.timestamp.to(),
initialized_block_env.number.to(), evm_env.block_env.number.to(),
parent_beacon_block_root, parent_beacon_block_root,
&mut evm, &mut evm,
)?; )?;
@ -258,14 +241,14 @@ where
pub fn post_block_withdrawal_requests_contract_call<DB>( pub fn post_block_withdrawal_requests_contract_call<DB>(
&mut self, &mut self,
db: &mut DB, db: &mut DB,
initialized_cfg: &CfgEnvWithHandlerCfg, evm_env: &EvmEnv,
initialized_block_env: &BlockEnv,
) -> Result<Bytes, BlockExecutionError> ) -> Result<Bytes, BlockExecutionError>
where where
DB: Database + DatabaseCommit, DB: Database + DatabaseCommit,
DB::Error: Display, DB::Error: Display,
{ {
let mut evm = initialize_evm(db, initialized_cfg, initialized_block_env); let evm_config = self.evm_config.clone();
let mut evm = evm_config.evm_with_env(db, evm_env.clone(), Default::default());
let result = self.apply_withdrawal_requests_contract_call(&mut evm)?; let result = self.apply_withdrawal_requests_contract_call(&mut evm)?;
@ -296,14 +279,14 @@ where
pub fn post_block_consolidation_requests_contract_call<DB>( pub fn post_block_consolidation_requests_contract_call<DB>(
&mut self, &mut self,
db: &mut DB, db: &mut DB,
initialized_cfg: &CfgEnvWithHandlerCfg, evm_env: &EvmEnv,
initialized_block_env: &BlockEnv,
) -> Result<Bytes, BlockExecutionError> ) -> Result<Bytes, BlockExecutionError>
where where
DB: Database + DatabaseCommit, DB: Database + DatabaseCommit,
DB::Error: Display, DB::Error: Display,
{ {
let mut evm = initialize_evm(db, initialized_cfg, initialized_block_env); let evm_config = self.evm_config.clone();
let mut evm = evm_config.evm_with_env(db, evm_env.clone(), Default::default());
let res = self.apply_consolidation_requests_contract_call(&mut evm)?; let res = self.apply_consolidation_requests_contract_call(&mut evm)?;

View File

@ -713,8 +713,7 @@ where
SystemCaller::new(self.evm_config.clone(), self.chain_spec.clone()) SystemCaller::new(self.evm_config.clone(), self.chain_spec.clone())
.pre_block_beacon_root_contract_call( .pre_block_beacon_root_contract_call(
db, db,
&self.evm_env.cfg_env_with_handler_cfg, &self.evm_env,
&self.evm_env.block_env,
self.attributes().payload_attributes.parent_beacon_block_root, self.attributes().payload_attributes.parent_beacon_block_root,
) )
.map_err(|err| { .map_err(|err| {

View File

@ -23,10 +23,7 @@ use reth_provider::{
}; };
use reth_revm::{ use reth_revm::{
database::StateProviderDatabase, database::StateProviderDatabase,
primitives::{ primitives::{BlockEnv, EVMError, ExecutionResult, InvalidTransaction, ResultAndState},
BlockEnv, CfgEnvWithHandlerCfg, EVMError, Env, ExecutionResult, InvalidTransaction,
ResultAndState,
},
}; };
use reth_rpc_eth_types::{EthApiError, PendingBlock, PendingBlockEnv, PendingBlockEnvOrigin}; use reth_rpc_eth_types::{EthApiError, PendingBlock, PendingBlockEnv, PendingBlockEnvOrigin};
use reth_transaction_pool::{ use reth_transaction_pool::{
@ -65,7 +62,7 @@ pub trait LoadPendingBlock:
&self, &self,
) -> &Mutex<Option<PendingBlock<ProviderBlock<Self::Provider>, ProviderReceipt<Self::Provider>>>>; ) -> &Mutex<Option<PendingBlock<ProviderBlock<Self::Provider>, ProviderReceipt<Self::Provider>>>>;
/// Configures the [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the pending block /// Configures the [`EvmEnv`] for the pending block
/// ///
/// If no pending block is available, this will derive it from the `latest` block /// If no pending block is available, this will derive it from the `latest` block
#[expect(clippy::type_complexity)] #[expect(clippy::type_complexity)]
@ -86,12 +83,10 @@ pub trait LoadPendingBlock:
// Note: for the PENDING block we assume it is past the known merge block and // 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 // thus this will not fail when looking up the total
// difficulty value for the blockenv. // difficulty value for the blockenv.
let EvmEnv { cfg_env_with_handler_cfg, block_env } = let evm_env = self.evm_config().cfg_and_block_env(block.header());
self.evm_config().cfg_and_block_env(block.header());
return Ok(PendingBlockEnv::new( return Ok(PendingBlockEnv::new(
cfg_env_with_handler_cfg, evm_env,
block_env,
PendingBlockEnvOrigin::ActualPending(block, receipts), PendingBlockEnvOrigin::ActualPending(block, receipts),
)); ));
} }
@ -105,7 +100,7 @@ pub trait LoadPendingBlock:
.map_err(Self::Error::from_eth_err)? .map_err(Self::Error::from_eth_err)?
.ok_or(EthApiError::HeaderNotFound(BlockNumberOrTag::Latest.into()))?; .ok_or(EthApiError::HeaderNotFound(BlockNumberOrTag::Latest.into()))?;
let EvmEnv { cfg_env_with_handler_cfg, block_env } = self let evm_env = self
.evm_config() .evm_config()
.next_cfg_and_block_env( .next_cfg_and_block_env(
&latest, &latest,
@ -119,11 +114,7 @@ pub trait LoadPendingBlock:
.map_err(RethError::other) .map_err(RethError::other)
.map_err(Self::Error::from_eth_err)?; .map_err(Self::Error::from_eth_err)?;
Ok(PendingBlockEnv::new( Ok(PendingBlockEnv::new(evm_env, PendingBlockEnvOrigin::DerivedFromLatest(latest.hash())))
cfg_env_with_handler_cfg,
block_env,
PendingBlockEnvOrigin::DerivedFromLatest(latest.hash()),
))
} }
/// Returns the locally built pending block /// Returns the locally built pending block
@ -159,7 +150,7 @@ pub trait LoadPendingBlock:
// check if the block is still good // check if the block is still good
if let Some(pending_block) = lock.as_ref() { if let Some(pending_block) = lock.as_ref() {
// this is guaranteed to be the `latest` header // this is guaranteed to be the `latest` header
if pending.block_env.number.to::<u64>() == pending_block.block.number() && if pending.evm_env.block_env.number.to::<u64>() == pending_block.block.number() &&
parent_hash == pending_block.block.parent_hash() && parent_hash == pending_block.block.parent_hash() &&
now <= pending_block.expires_at now <= pending_block.expires_at
{ {
@ -171,7 +162,7 @@ pub trait LoadPendingBlock:
let (sealed_block, receipts) = match self let (sealed_block, receipts) = match self
.spawn_blocking_io(move |this| { .spawn_blocking_io(move |this| {
// we rebuild the block // we rebuild the block
this.build_block(pending.cfg, pending.block_env, parent_hash) this.build_block(pending.evm_env, parent_hash)
}) })
.await .await
{ {
@ -243,8 +234,7 @@ pub trait LoadPendingBlock:
#[expect(clippy::type_complexity)] #[expect(clippy::type_complexity)]
fn build_block( fn build_block(
&self, &self,
cfg: CfgEnvWithHandlerCfg, evm_env: EvmEnv,
block_env: BlockEnv,
parent_hash: B256, parent_hash: B256,
) -> Result< ) -> Result<
(RecoveredBlock<ProviderBlock<Self::Provider>>, Vec<ProviderReceipt<Self::Provider>>), (RecoveredBlock<ProviderBlock<Self::Provider>>, Vec<ProviderReceipt<Self::Provider>>),
@ -262,15 +252,15 @@ pub trait LoadPendingBlock:
let mut cumulative_gas_used = 0; let mut cumulative_gas_used = 0;
let mut sum_blob_gas_used = 0; let mut sum_blob_gas_used = 0;
let block_gas_limit: u64 = block_env.gas_limit.to::<u64>(); let block_gas_limit: u64 = evm_env.block_env.gas_limit.to::<u64>();
let base_fee = block_env.basefee.to::<u64>(); let base_fee = evm_env.block_env.basefee.to::<u64>();
let mut executed_txs = Vec::new(); let mut executed_txs = Vec::new();
let mut senders = Vec::new(); let mut senders = Vec::new();
let mut best_txs = let mut best_txs =
self.pool().best_transactions_with_attributes(BestTransactionsAttributes::new( self.pool().best_transactions_with_attributes(BestTransactionsAttributes::new(
base_fee, base_fee,
block_env.get_blob_gasprice().map(|gasprice| gasprice as u64), evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64),
)); ));
let chain_spec = self.provider().chain_spec(); let chain_spec = self.provider().chain_spec();
@ -278,7 +268,7 @@ pub trait LoadPendingBlock:
let mut system_caller = SystemCaller::new(self.evm_config().clone(), chain_spec.clone()); let mut system_caller = SystemCaller::new(self.evm_config().clone(), chain_spec.clone());
system_caller system_caller
.pre_block_blockhashes_contract_call(&mut db, &cfg, &block_env, parent_hash) .pre_block_blockhashes_contract_call(&mut db, &evm_env, parent_hash)
.map_err(|err| EthApiError::Internal(err.into()))?; .map_err(|err| EthApiError::Internal(err.into()))?;
let mut results = Vec::new(); let mut results = Vec::new();
@ -334,14 +324,8 @@ pub trait LoadPendingBlock:
} }
} }
// Configure the environment for the block. let tx_env = self.evm_config().tx_env(tx.tx(), tx.signer());
let env = Env::boxed( let mut evm = self.evm_config().evm_with_env(&mut db, evm_env.clone(), tx_env);
cfg.cfg_env.clone(),
block_env.clone(),
Self::evm_config(self).tx_env(tx.tx(), tx.signer()),
);
let mut evm = revm::Evm::builder().with_env(env).with_db(&mut db).build();
let ResultAndState { result, state } = match evm.transact() { let ResultAndState { result, state } = match evm.transact() {
Ok(res) => res, Ok(res) => res,
@ -399,7 +383,7 @@ pub trait LoadPendingBlock:
// executes the withdrawals and commits them to the Database and BundleState. // executes the withdrawals and commits them to the Database and BundleState.
let balance_increments = post_block_withdrawals_balance_increments( let balance_increments = post_block_withdrawals_balance_increments(
chain_spec.as_ref(), chain_spec.as_ref(),
block_env.timestamp.try_into().unwrap_or(u64::MAX), evm_env.block_env.timestamp.try_into().unwrap_or(u64::MAX),
&[], &[],
); );
@ -416,7 +400,7 @@ pub trait LoadPendingBlock:
let state_root = db.database.state_root(hashed_state).map_err(Self::Error::from_eth_err)?; let state_root = db.database.state_root(hashed_state).map_err(Self::Error::from_eth_err)?;
let (block, receipts) = self.assemble_block_and_receipts( let (block, receipts) = self.assemble_block_and_receipts(
&block_env, &evm_env.block_env,
parent_hash, parent_hash,
state_root, state_root,
executed_txs, executed_txs,

View File

@ -219,9 +219,8 @@ pub trait LoadState:
{ {
async move { async move {
if at.is_pending() { if at.is_pending() {
let PendingBlockEnv { cfg, block_env, origin } = let PendingBlockEnv { evm_env, origin } = self.pending_block_env_and_cfg()?;
self.pending_block_env_and_cfg()?; Ok((evm_env, origin.state_block_id()))
Ok(((cfg, block_env).into(), origin.state_block_id()))
} else { } else {
// Use cached values if there is no pending block // Use cached values if there is no pending block
let block_hash = RpcNodeCore::provider(self) let block_hash = RpcNodeCore::provider(self)

View File

@ -457,21 +457,11 @@ pub trait Trace:
SystemCaller::new(self.evm_config().clone(), self.provider().chain_spec()); SystemCaller::new(self.evm_config().clone(), self.provider().chain_spec());
// apply relevant system calls // apply relevant system calls
system_caller system_caller
.pre_block_beacon_root_contract_call( .pre_block_beacon_root_contract_call(db, evm_env, block.parent_beacon_block_root())
db,
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()))?; .map_err(|_| EthApiError::EvmCustom("failed to apply 4788 system call".to_string()))?;
system_caller system_caller
.pre_block_blockhashes_contract_call( .pre_block_blockhashes_contract_call(db, evm_env, block.parent_hash())
db,
evm_env.cfg_env_with_handler_cfg(),
evm_env.block_env(),
block.parent_hash(),
)
.map_err(|_| { .map_err(|_| {
EthApiError::EvmCustom("failed to apply blockhashes system call".to_string()) EthApiError::EvmCustom("failed to apply blockhashes system call".to_string())
})?; })?;

View File

@ -15,6 +15,7 @@ workspace = true
reth-chainspec.workspace = true reth-chainspec.workspace = true
reth-chain-state.workspace = true reth-chain-state.workspace = true
reth-errors.workspace = true reth-errors.workspace = true
reth-evm.workspace = true
reth-execution-types.workspace = true reth-execution-types.workspace = true
reth-metrics.workspace = true reth-metrics.workspace = true
reth-primitives = { workspace = true, features = ["secp256k1"] } reth-primitives = { workspace = true, features = ["secp256k1"] }

View File

@ -8,17 +8,15 @@ use alloy_consensus::BlockHeader;
use alloy_eips::{BlockId, BlockNumberOrTag}; use alloy_eips::{BlockId, BlockNumberOrTag};
use alloy_primitives::B256; use alloy_primitives::B256;
use derive_more::Constructor; use derive_more::Constructor;
use reth_evm::EvmEnv;
use reth_primitives::{Receipt, RecoveredBlock}; use reth_primitives::{Receipt, RecoveredBlock};
use reth_primitives_traits::Block; use reth_primitives_traits::Block;
use revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg};
/// Configured [`BlockEnv`] and [`CfgEnvWithHandlerCfg`] for a pending block. /// Configured [`EvmEnv`] for a pending block.
#[derive(Debug, Clone, Constructor)] #[derive(Debug, Clone, Constructor)]
pub struct PendingBlockEnv<B: Block = reth_primitives::Block, R = Receipt> { pub struct PendingBlockEnv<B: Block = reth_primitives::Block, R = Receipt> {
/// Configured [`CfgEnvWithHandlerCfg`] for the pending block. /// Configured [`EvmEnv`] for the pending block.
pub cfg: CfgEnvWithHandlerCfg, pub evm_env: EvmEnv,
/// Configured [`BlockEnv`] for the pending block.
pub block_env: BlockEnv,
/// Origin block for the config /// Origin block for the config
pub origin: PendingBlockEnvOrigin<B, R>, pub origin: PendingBlockEnvOrigin<B, R>,
} }