mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: add evm_for_block helper to simplify EVM setup (#13787)
This commit is contained in:
@ -6,15 +6,14 @@ use pretty_assertions::Comparison;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks};
|
||||
use reth_engine_primitives::InvalidBlockHook;
|
||||
use reth_evm::{
|
||||
env::EvmEnv, state_change::post_block_balance_increments, system_calls::SystemCaller,
|
||||
ConfigureEvm,
|
||||
state_change::post_block_balance_increments, system_calls::SystemCaller, ConfigureEvm,
|
||||
};
|
||||
use reth_primitives::{NodePrimitives, SealedBlockWithSenders, SealedHeader};
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_provider::{BlockExecutionOutput, ChainSpecProvider, StateProviderFactory};
|
||||
use reth_revm::{
|
||||
database::StateProviderDatabase, db::states::bundle_state::BundleRetention,
|
||||
primitives::EnvWithHandlerCfg, DatabaseCommit, StateBuilder,
|
||||
database::StateProviderDatabase, db::states::bundle_state::BundleRetention, DatabaseCommit,
|
||||
StateBuilder,
|
||||
};
|
||||
use reth_rpc_api::DebugApiClient;
|
||||
use reth_tracing::tracing::warn;
|
||||
@ -77,19 +76,8 @@ where
|
||||
.with_bundle_update()
|
||||
.build();
|
||||
|
||||
// Setup environment for the execution.
|
||||
let EvmEnv { cfg_env_with_handler_cfg, block_env } =
|
||||
self.evm_config.cfg_and_block_env(block.header());
|
||||
|
||||
// Setup EVM
|
||||
let mut evm = self.evm_config.evm_with_env(
|
||||
&mut db,
|
||||
EnvWithHandlerCfg::new_with_cfg_env(
|
||||
cfg_env_with_handler_cfg,
|
||||
block_env,
|
||||
Default::default(),
|
||||
),
|
||||
);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut db, block.header());
|
||||
|
||||
let mut system_caller =
|
||||
SystemCaller::new(self.evm_config.clone(), self.provider.chain_spec());
|
||||
|
||||
@ -14,8 +14,8 @@ use reth_engine_primitives::{
|
||||
use reth_errors::{BlockExecutionError, BlockValidationError, RethError, RethResult};
|
||||
use reth_ethereum_forks::EthereumHardforks;
|
||||
use reth_evm::{
|
||||
env::EvmEnv, state_change::post_block_withdrawals_balance_increments,
|
||||
system_calls::SystemCaller, ConfigureEvm,
|
||||
state_change::post_block_withdrawals_balance_increments, system_calls::SystemCaller,
|
||||
ConfigureEvm,
|
||||
};
|
||||
use reth_payload_validator::ExecutionPayloadValidator;
|
||||
use reth_primitives::{
|
||||
@ -29,7 +29,7 @@ use reth_revm::{
|
||||
DatabaseCommit,
|
||||
};
|
||||
use reth_rpc_types_compat::engine::payload::block_to_payload;
|
||||
use revm_primitives::{EVMError, EnvWithHandlerCfg};
|
||||
use revm_primitives::EVMError;
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
future::Future,
|
||||
@ -297,15 +297,8 @@ where
|
||||
.with_bundle_update()
|
||||
.build();
|
||||
|
||||
// Configure environments
|
||||
let EvmEnv { cfg_env_with_handler_cfg, block_env } =
|
||||
evm_config.cfg_and_block_env(&reorg_target.header);
|
||||
let env = EnvWithHandlerCfg::new_with_cfg_env(
|
||||
cfg_env_with_handler_cfg,
|
||||
block_env,
|
||||
Default::default(),
|
||||
);
|
||||
let mut evm = evm_config.evm_with_env(&mut state, env);
|
||||
// Configure EVM
|
||||
let mut evm = evm_config.evm_for_block(&mut state, &reorg_target.header);
|
||||
|
||||
// apply eip-4788 pre block contract call
|
||||
let mut system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone());
|
||||
|
||||
@ -12,7 +12,6 @@ use reth_chainspec::{ChainSpec, EthereumHardfork, EthereumHardforks, MAINNET};
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_ethereum_consensus::validate_block_post_execution;
|
||||
use reth_evm::{
|
||||
env::EvmEnv,
|
||||
execute::{
|
||||
balance_increment_state, BasicBlockExecutorProvider, BlockExecutionError,
|
||||
BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, ExecuteOutput,
|
||||
@ -26,7 +25,7 @@ use reth_primitives::{BlockWithSenders, EthPrimitives, Receipt};
|
||||
use reth_revm::db::State;
|
||||
use revm_primitives::{
|
||||
db::{Database, DatabaseCommit},
|
||||
EnvWithHandlerCfg, ResultAndState,
|
||||
ResultAndState,
|
||||
};
|
||||
|
||||
/// Factory for [`EthExecutionStrategy`].
|
||||
@ -113,23 +112,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB, EvmConfig> EthExecutionStrategy<DB, EvmConfig>
|
||||
where
|
||||
DB: Database<Error: Into<ProviderError> + Display>,
|
||||
EvmConfig: ConfigureEvm,
|
||||
{
|
||||
/// Configures a new evm configuration and block environment for the given block.
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This does not initialize the tx environment.
|
||||
fn evm_env_for_block(&self, header: &EvmConfig::Header) -> EnvWithHandlerCfg {
|
||||
let EvmEnv { cfg_env_with_handler_cfg, block_env } =
|
||||
self.evm_config.cfg_and_block_env(header);
|
||||
EnvWithHandlerCfg::new_with_cfg_env(cfg_env_with_handler_cfg, block_env, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB, EvmConfig> BlockExecutionStrategy for EthExecutionStrategy<DB, EvmConfig>
|
||||
where
|
||||
DB: Database<Error: Into<ProviderError> + Display>,
|
||||
@ -153,8 +135,7 @@ where
|
||||
(*self.chain_spec).is_spurious_dragon_active_at_block(block.header.number);
|
||||
self.state.set_state_clear_flag(state_clear_flag);
|
||||
|
||||
let env = self.evm_env_for_block(&block.header);
|
||||
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut self.state, &block.header);
|
||||
|
||||
self.system_caller.apply_pre_execution_changes(&block.header, &mut evm)?;
|
||||
|
||||
@ -165,8 +146,7 @@ where
|
||||
&mut self,
|
||||
block: &BlockWithSenders,
|
||||
) -> Result<ExecuteOutput<Receipt>, Self::Error> {
|
||||
let env = self.evm_env_for_block(&block.header);
|
||||
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut self.state, &block.header);
|
||||
|
||||
let mut cumulative_gas_used = 0;
|
||||
let mut receipts = Vec::with_capacity(block.body.transactions.len());
|
||||
@ -227,8 +207,7 @@ where
|
||||
block: &BlockWithSenders,
|
||||
receipts: &[Receipt],
|
||||
) -> Result<Requests, Self::Error> {
|
||||
let env = self.evm_env_for_block(&block.header);
|
||||
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut self.state, &block.header);
|
||||
|
||||
let requests = if self.chain_spec.is_prague_active_at_timestamp(block.timestamp) {
|
||||
// Collect all EIP-6110 deposits
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
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};
|
||||
@ -41,7 +42,6 @@ pub mod system_calls;
|
||||
pub mod test_utils;
|
||||
|
||||
/// Trait for configuring the EVM for executing full blocks.
|
||||
#[auto_impl::auto_impl(&, Arc)]
|
||||
pub trait ConfigureEvm: ConfigureEvmEnv {
|
||||
/// Associated type for the default external context that should be configured for the EVM.
|
||||
type DefaultExternalContext<'a>;
|
||||
@ -70,6 +70,31 @@ pub trait ConfigureEvm: ConfigureEvmEnv {
|
||||
evm
|
||||
}
|
||||
|
||||
/// 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`].
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This does not initialize the tx environment.
|
||||
fn evm_for_block<DB: Database>(
|
||||
&self,
|
||||
db: DB,
|
||||
header: &Self::Header,
|
||||
) -> Evm<'_, Self::DefaultExternalContext<'_>, 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,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a new EVM with the given database configured with the given environment settings,
|
||||
/// including the spec id.
|
||||
///
|
||||
@ -109,6 +134,59 @@ pub trait ConfigureEvm: ConfigureEvmEnv {
|
||||
fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a>;
|
||||
}
|
||||
|
||||
impl<'b, T> ConfigureEvm for &'b T
|
||||
where
|
||||
T: ConfigureEvm,
|
||||
&'b T: ConfigureEvmEnv<Header = T::Header>,
|
||||
{
|
||||
type DefaultExternalContext<'a> = T::DefaultExternalContext<'a>;
|
||||
|
||||
fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a> {
|
||||
(*self).default_external_context()
|
||||
}
|
||||
|
||||
fn evm<DB: Database>(&self, db: DB) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> {
|
||||
(*self).evm(db)
|
||||
}
|
||||
|
||||
fn evm_for_block<DB: Database>(
|
||||
&self,
|
||||
db: DB,
|
||||
header: &Self::Header,
|
||||
) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> {
|
||||
(*self).evm_for_block(db, header)
|
||||
}
|
||||
|
||||
fn evm_with_env<DB: Database>(
|
||||
&self,
|
||||
db: DB,
|
||||
env: EnvWithHandlerCfg,
|
||||
) -> Evm<'_, Self::DefaultExternalContext<'_>, DB> {
|
||||
(*self).evm_with_env(db, env)
|
||||
}
|
||||
|
||||
fn evm_with_env_and_inspector<DB, I>(
|
||||
&self,
|
||||
db: DB,
|
||||
env: EnvWithHandlerCfg,
|
||||
inspector: I,
|
||||
) -> Evm<'_, I, DB>
|
||||
where
|
||||
DB: Database,
|
||||
I: GetInspector<DB>,
|
||||
{
|
||||
(*self).evm_with_env_and_inspector(db, env, inspector)
|
||||
}
|
||||
|
||||
fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
|
||||
where
|
||||
DB: Database,
|
||||
I: GetInspector<DB>,
|
||||
{
|
||||
(*self).evm_with_inspector(db, inspector)
|
||||
}
|
||||
}
|
||||
|
||||
/// This represents the set of methods used to configure the EVM's environment before block
|
||||
/// execution.
|
||||
///
|
||||
|
||||
@ -2,14 +2,13 @@
|
||||
|
||||
use crate::{l1::ensure_create2_deployer, OpBlockExecutionError, OpEvmConfig};
|
||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloy_consensus::{Eip658Value, Header, Receipt, Transaction as _};
|
||||
use alloy_consensus::{Eip658Value, Receipt, Transaction as _};
|
||||
use alloy_eips::eip7685::Requests;
|
||||
use core::fmt::Display;
|
||||
use op_alloy_consensus::{OpDepositReceipt, OpTxType};
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_evm::{
|
||||
env::EvmEnv,
|
||||
execute::{
|
||||
balance_increment_state, BasicBlockExecutorProvider, BlockExecutionError,
|
||||
BlockExecutionStrategy, BlockExecutionStrategyFactory, BlockValidationError, ExecuteOutput,
|
||||
@ -26,7 +25,7 @@ use reth_optimism_primitives::{OpBlock, OpPrimitives, OpReceipt, OpTransactionSi
|
||||
use reth_primitives::BlockWithSenders;
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use reth_revm::{Database, State};
|
||||
use revm_primitives::{db::DatabaseCommit, EnvWithHandlerCfg, ResultAndState};
|
||||
use revm_primitives::{db::DatabaseCommit, ResultAndState};
|
||||
use tracing::trace;
|
||||
|
||||
/// Factory for [`OpExecutionStrategy`].
|
||||
@ -104,21 +103,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB, EvmConfig> OpExecutionStrategy<DB, EvmConfig>
|
||||
where
|
||||
DB: Database<Error: Into<ProviderError> + Display>,
|
||||
EvmConfig: ConfigureEvm<Header = alloy_consensus::Header>,
|
||||
{
|
||||
/// Configures a new evm configuration and block environment for the given block.
|
||||
///
|
||||
/// Caution: this does not initialize the tx environment.
|
||||
fn evm_env_for_block(&self, header: &Header) -> EnvWithHandlerCfg {
|
||||
let evm_env = self.evm_config.cfg_and_block_env(header);
|
||||
let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env;
|
||||
EnvWithHandlerCfg::new_with_cfg_env(cfg_env_with_handler_cfg, block_env, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB, EvmConfig> BlockExecutionStrategy for OpExecutionStrategy<DB, EvmConfig>
|
||||
where
|
||||
DB: Database<Error: Into<ProviderError> + Display>,
|
||||
@ -141,8 +125,7 @@ where
|
||||
(*self.chain_spec).is_spurious_dragon_active_at_block(block.header.number);
|
||||
self.state.set_state_clear_flag(state_clear_flag);
|
||||
|
||||
let env = self.evm_env_for_block(&block.header);
|
||||
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut self.state, &block.header);
|
||||
|
||||
self.system_caller.apply_beacon_root_contract_call(
|
||||
block.timestamp,
|
||||
@ -165,8 +148,7 @@ where
|
||||
&mut self,
|
||||
block: &BlockWithSenders<OpBlock>,
|
||||
) -> Result<ExecuteOutput<OpReceipt>, Self::Error> {
|
||||
let env = self.evm_env_for_block(&block.header);
|
||||
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut self.state, &block.header);
|
||||
|
||||
let is_regolith =
|
||||
self.chain_spec.fork(OpHardfork::Regolith).active_at_timestamp(block.timestamp);
|
||||
@ -318,7 +300,7 @@ impl OpExecutorProvider {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::OpChainSpec;
|
||||
use alloy_consensus::TxEip1559;
|
||||
use alloy_consensus::{Header, TxEip1559};
|
||||
use alloy_primitives::{
|
||||
b256, Address, PrimitiveSignature as Signature, StorageKey, StorageValue, U256,
|
||||
};
|
||||
|
||||
@ -9,23 +9,20 @@ use alloy_sol_types::SolCall;
|
||||
#[cfg(feature = "optimism")]
|
||||
use reth::revm::primitives::OptimismFields;
|
||||
use reth::{
|
||||
api::{ConfigureEvm, ConfigureEvmEnv, NodeTypesWithEngine},
|
||||
api::{ConfigureEvm, NodeTypesWithEngine},
|
||||
builder::{components::ExecutorBuilder, BuilderContext, FullNodeTypes},
|
||||
cli::Cli,
|
||||
providers::ProviderError,
|
||||
revm::{
|
||||
interpreter::Host,
|
||||
primitives::{address, Address, Bytes, Env, EnvWithHandlerCfg, TransactTo, TxEnv, U256},
|
||||
primitives::{address, Address, Bytes, Env, TransactTo, TxEnv, U256},
|
||||
Database, DatabaseCommit, Evm, State,
|
||||
},
|
||||
};
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_evm::{
|
||||
env::EvmEnv,
|
||||
execute::{
|
||||
BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, ExecuteOutput,
|
||||
InternalBlockExecutionError,
|
||||
},
|
||||
use reth_evm::execute::{
|
||||
BlockExecutionError, BlockExecutionStrategy, BlockExecutionStrategyFactory, ExecuteOutput,
|
||||
InternalBlockExecutionError,
|
||||
};
|
||||
use reth_evm_ethereum::EthEvmConfig;
|
||||
use reth_node_ethereum::{node::EthereumAddOns, BasicBlockExecutorProvider, EthereumNode};
|
||||
@ -120,22 +117,6 @@ where
|
||||
state: State<DB>,
|
||||
}
|
||||
|
||||
impl<DB> CustomExecutorStrategy<DB>
|
||||
where
|
||||
DB: Database<Error: Into<ProviderError> + Display>,
|
||||
{
|
||||
/// Configures a new evm configuration and block environment for the given block.
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// This does not initialize the tx environment.
|
||||
fn evm_env_for_block(&self, header: &alloy_consensus::Header) -> EnvWithHandlerCfg {
|
||||
let evm_env = self.evm_config.cfg_and_block_env(header);
|
||||
let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env;
|
||||
EnvWithHandlerCfg::new_with_cfg_env(cfg_env_with_handler_cfg, block_env, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> BlockExecutionStrategy for CustomExecutorStrategy<DB>
|
||||
where
|
||||
DB: Database<Error: Into<ProviderError> + Display>,
|
||||
@ -165,8 +146,7 @@ where
|
||||
block: &BlockWithSenders,
|
||||
_receipts: &[Receipt],
|
||||
) -> Result<Requests, Self::Error> {
|
||||
let env = self.evm_env_for_block(&block.header);
|
||||
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
|
||||
let mut evm = self.evm_config.evm_for_block(&mut self.state, &block.header);
|
||||
|
||||
if let Some(withdrawals) = block.body.withdrawals.as_ref() {
|
||||
apply_withdrawals_contract_call(withdrawals, &mut evm)?;
|
||||
|
||||
Reference in New Issue
Block a user