ConfigureEvm

Trait ConfigureEvm 

Source
pub trait ConfigureEvm:
    Clone
    + Debug
    + Send
    + Sync
    + Unpin {
    type Primitives: NodePrimitives;
    type Error: Error + Send + Sync + 'static;
    type NextBlockEnvCtx: Debug + Clone;
    type BlockExecutorFactory: for<'a> BlockExecutorFactory<Transaction = TxTy<Self::Primitives>, Receipt = ReceiptTy<Self::Primitives>, ExecutionCtx<'a>: Debug + Send, EvmFactory: EvmFactory<Tx: TransactionEnv + FromRecoveredTx<TxTy<Self::Primitives>> + FromTxWithEncoded<TxTy<Self::Primitives>>, Precompiles = PrecompilesMap>>;
    type BlockAssembler: BlockAssembler<Self::BlockExecutorFactory, Block = BlockTy<Self::Primitives>>;

Show 17 methods // Required methods fn block_executor_factory(&self) -> &Self::BlockExecutorFactory; fn block_assembler(&self) -> &Self::BlockAssembler; fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>; fn next_evm_env( &self, parent: &HeaderTy<Self::Primitives>, attributes: &Self::NextBlockEnvCtx, ) -> Result<EvmEnvFor<Self>, Self::Error>; fn context_for_block<'a>( &self, block: &'a SealedBlock<BlockTy<Self::Primitives>>, ) -> ExecutionCtxFor<'a, Self>; fn context_for_next_block( &self, parent: &SealedHeader<HeaderTy<Self::Primitives>>, attributes: Self::NextBlockEnvCtx, ) -> ExecutionCtxFor<'_, Self>; // Provided methods fn tx_env( &self, transaction: impl IntoTxEnv<TxEnvFor<Self>>, ) -> TxEnvFor<Self> { ... } fn evm_factory(&self) -> &EvmFactoryFor<Self> { ... } fn evm_with_env<DB: Database>( &self, db: DB, evm_env: EvmEnvFor<Self>, ) -> EvmFor<Self, DB> { ... } fn evm_for_block<DB: Database>( &self, db: DB, header: &HeaderTy<Self::Primitives>, ) -> EvmFor<Self, DB> { ... } fn evm_with_env_and_inspector<DB, I>( &self, db: DB, evm_env: EvmEnvFor<Self>, inspector: I, ) -> EvmFor<Self, DB, I> where DB: Database, I: InspectorFor<Self, DB> { ... } fn create_executor<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I> where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a { ... } fn executor_for_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB> { ... } fn create_block_builder<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, parent: &'a SealedHeader<HeaderTy<Self::Primitives>>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>> where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a { ... } fn builder_for_next_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>, attributes: Self::NextBlockEnvCtx, ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error> { ... } fn executor<DB: Database>( &self, db: DB, ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> { ... } fn batch_executor<DB: Database>( &self, db: DB, ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> { ... }
}
Expand description

A complete configuration of EVM for Reth.

This trait encapsulates complete configuration required for transaction execution and block execution/building, providing a unified interface for EVM operations.

§Architecture Overview

The EVM abstraction consists of the following layers:

  1. Evm (produced by EvmFactory): The core EVM implementation responsible for executing individual transactions and producing outputs including state changes, logs, gas usage, etc.

  2. BlockExecutor (produced by BlockExecutorFactory): A higher-level component that operates on top of Evm to execute entire blocks. This involves:

    • Executing all transactions in sequence
    • Building receipts from transaction outputs
    • Applying block rewards to the beneficiary
    • Executing system calls (e.g., EIP-4788 beacon root updates)
    • Managing state changes and bundle accumulation
  3. BlockAssembler: Responsible for assembling valid blocks from executed transactions. It takes the output from BlockExecutor along with execution context and produces a complete block ready for inclusion in the chain.

§Usage Patterns

The abstraction supports two primary use cases:

§1. Executing Externally Provided Blocks (e.g., during sync)

use reth_evm::ConfigureEvm;

// Execute a received block
let mut executor = evm_config.executor(state_db);
let output = executor.execute(&block)?;

// Access the execution results
println!("Gas used: {}", output.result.gas_used);
println!("Receipts: {:?}", output.result.receipts);

§2. Building New Blocks (e.g., payload building)

Payload building is slightly different as it doesn’t have the block’s header yet, but rather attributes for the block’s environment, such as timestamp, fee recipient, and randomness value. The block’s header will be the outcome of the block building process.

use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};

// Create attributes for the next block
let attributes = NextBlockEnvAttributes {
    timestamp: current_time + 12,
    suggested_fee_recipient: beneficiary_address,
    prev_randao: randomness_value,
    gas_limit: 30_000_000,
    withdrawals: Some(withdrawals),
    parent_beacon_block_root: Some(beacon_root),
};

// Build a new block on top of parent
let mut builder = evm_config.builder_for_next_block(
    &mut state_db,
    &parent_header,
    attributes
)?;

// Apply pre-execution changes (e.g., beacon root update)
builder.apply_pre_execution_changes()?;

// Execute transactions
for tx in pending_transactions {
    match builder.execute_transaction(tx) {
        Ok(gas_used) => {
            println!("Transaction executed, gas used: {}", gas_used);
        }
        Err(e) => {
            println!("Transaction failed: {:?}", e);
        }
    }
}

// Finish block building and get the outcome (block)
let outcome = builder.finish(state_provider)?;
let block = outcome.block;

§Key Components

§NextBlockEnvCtx

Contains attributes needed to configure the next block that cannot be derived from the parent block alone. This includes data typically provided by the consensus layer:

  • timestamp: Block timestamp
  • suggested_fee_recipient: Beneficiary address
  • prev_randao: Randomness value
  • gas_limit: Block gas limit
  • withdrawals: Consensus layer withdrawals
  • parent_beacon_block_root: EIP-4788 beacon root

§BlockAssembler

Takes the execution output and produces a complete block. It receives:

  • Transaction execution results (receipts, gas used)
  • Final state root after all executions
  • Bundle state with all changes
  • Execution context and environment

The assembler is responsible for:

  • Setting the correct block header fields
  • Including executed transactions
  • Setting gas used and receipts root
  • Applying any chain-specific rules

Required Associated Types§

Source

type Primitives: NodePrimitives

The primitives type used by the EVM.

Source

type Error: Error + Send + Sync + 'static

The error type that is returned by Self::next_evm_env.

Source

type NextBlockEnvCtx: Debug + Clone

Context required for configuring next block environment.

Contains values that can’t be derived from the parent block.

Source

type BlockExecutorFactory: for<'a> BlockExecutorFactory<Transaction = TxTy<Self::Primitives>, Receipt = ReceiptTy<Self::Primitives>, ExecutionCtx<'a>: Debug + Send, EvmFactory: EvmFactory<Tx: TransactionEnv + FromRecoveredTx<TxTy<Self::Primitives>> + FromTxWithEncoded<TxTy<Self::Primitives>>, Precompiles = PrecompilesMap>>

Configured BlockExecutorFactory, contains EvmFactory internally.

Source

type BlockAssembler: BlockAssembler<Self::BlockExecutorFactory, Block = BlockTy<Self::Primitives>>

A type that knows how to build a block.

Required Methods§

Source

fn block_executor_factory(&self) -> &Self::BlockExecutorFactory

Returns reference to the configured BlockExecutorFactory.

Source

fn block_assembler(&self) -> &Self::BlockAssembler

Returns reference to the configured BlockAssembler.

Source

fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>

Creates a new EvmEnv for the given header.

Source

fn next_evm_env( &self, parent: &HeaderTy<Self::Primitives>, attributes: &Self::NextBlockEnvCtx, ) -> Result<EvmEnvFor<Self>, Self::Error>

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.

§Example
let evm_env = evm_config.next_evm_env(&parent_header, &attributes)?;
// evm_env now contains:
// - Correct spec ID based on timestamp and block number
// - Block environment with next block's parameters
// - Configuration like chain ID and blob parameters
Source

fn context_for_block<'a>( &self, block: &'a SealedBlock<BlockTy<Self::Primitives>>, ) -> ExecutionCtxFor<'a, Self>

Returns the configured BlockExecutorFactory::ExecutionCtx for a given block.

Source

fn context_for_next_block( &self, parent: &SealedHeader<HeaderTy<Self::Primitives>>, attributes: Self::NextBlockEnvCtx, ) -> ExecutionCtxFor<'_, Self>

Returns the configured BlockExecutorFactory::ExecutionCtx for parent + 1 block.

Provided Methods§

Source

fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self>

Returns a TxEnv from a transaction and Address.

Source

fn evm_factory(&self) -> &EvmFactoryFor<Self>

Provides a reference to EvmFactory implementation.

Source

fn evm_with_env<DB: Database>( &self, db: DB, evm_env: EvmEnvFor<Self>, ) -> EvmFor<Self, DB>

Returns a new EVM with the given database configured with the given environment settings, including the spec id and transaction environment.

This will preserve any handler modifications

Source

fn evm_for_block<DB: Database>( &self, db: DB, header: &HeaderTy<Self::Primitives>, ) -> EvmFor<Self, DB>

Returns a new EVM with the given database configured with cfg and block_env configuration derived from the given header. Relies on ConfigureEvm::evm_env.

§Caution

This does not initialize the tx environment.

Source

fn evm_with_env_and_inspector<DB, I>( &self, db: DB, evm_env: EvmEnvFor<Self>, inspector: I, ) -> EvmFor<Self, DB, I>
where DB: Database, I: InspectorFor<Self, DB>,

Returns a new EVM with the given database configured with the given environment settings, including the spec id.

This will use the given external inspector as the EVM external context.

This will preserve any handler modifications

Source

fn create_executor<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a,

Creates a strategy with given EVM and execution context.

Source

fn executor_for_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>

Creates a strategy for execution of a given block.

Source

fn create_block_builder<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, parent: &'a SealedHeader<HeaderTy<Self::Primitives>>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>>
where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a,

Creates a BlockBuilder. Should be used when building a new block.

Block builder wraps an inner alloy_evm::block::BlockExecutor and has a similar interface. Builder collects all of the executed transactions, and once BlockBuilder::finish is called, it invokes the configured BlockAssembler to create a block.

§Example
// Create a builder with specific EVM configuration
let evm = evm_config.evm_with_env(&mut state_db, evm_env);
let ctx = evm_config.context_for_next_block(&parent, attributes);
let builder = evm_config.create_block_builder(evm, &parent, ctx);
Source

fn builder_for_next_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>, attributes: Self::NextBlockEnvCtx, ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error>

Creates a BlockBuilder for building of a new block. This is a helper to invoke ConfigureEvm::create_block_builder.

This is the primary method for building new blocks. It combines:

  1. Creating the EVM environment for the next block
  2. Setting up the execution context from attributes
  3. Initializing the block builder with proper configuration
§Example
// Build a block with specific attributes
let mut builder = evm_config.builder_for_next_block(
    &mut state_db,
    &parent_header,
    attributes
)?;

// Execute system calls (e.g., beacon root update)
builder.apply_pre_execution_changes()?;

// Execute transactions
for tx in transactions {
    builder.execute_transaction(tx)?;
}

// Complete block building
let outcome = builder.finish(state_provider)?;
Source

fn executor<DB: Database>( &self, db: DB, ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>

Returns a new Executor for executing blocks.

The executor processes complete blocks including:

  • All transactions in order
  • Block rewards and fees
  • Block level system calls
  • State transitions
§Example
// Create an executor
let mut executor = evm_config.executor(state_db);

// Execute a single block
let output = executor.execute(&block)?;

// Execute multiple blocks
let batch_output = executor.execute_batch(&blocks)?;
Source

fn batch_executor<DB: Database>( &self, db: DB, ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError>

Returns a new BasicBlockExecutor.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl<'b, T: 'b + ConfigureEvm + ?Sized> ConfigureEvm for &'b T
where &'b T: Clone + Debug + Send + Sync + Unpin,

Source§

type Primitives = <T as ConfigureEvm>::Primitives

Source§

type Error = <T as ConfigureEvm>::Error

Source§

type NextBlockEnvCtx = <T as ConfigureEvm>::NextBlockEnvCtx

Source§

type BlockExecutorFactory = <T as ConfigureEvm>::BlockExecutorFactory

Source§

type BlockAssembler = <T as ConfigureEvm>::BlockAssembler

Source§

fn block_executor_factory(&self) -> &Self::BlockExecutorFactory

Source§

fn block_assembler(&self) -> &Self::BlockAssembler

Source§

fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>

Source§

fn next_evm_env( &self, parent: &HeaderTy<Self::Primitives>, attributes: &Self::NextBlockEnvCtx, ) -> Result<EvmEnvFor<Self>, Self::Error>

Source§

fn context_for_block<'a>( &self, block: &'a SealedBlock<BlockTy<Self::Primitives>>, ) -> ExecutionCtxFor<'a, Self>

Source§

fn context_for_next_block( &self, parent: &SealedHeader<HeaderTy<Self::Primitives>>, attributes: Self::NextBlockEnvCtx, ) -> ExecutionCtxFor<'_, Self>

Source§

fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self>

Source§

fn evm_factory(&self) -> &EvmFactoryFor<Self>

Source§

fn evm_with_env<DB: Database>( &self, db: DB, evm_env: EvmEnvFor<Self>, ) -> EvmFor<Self, DB>

Source§

fn evm_for_block<DB: Database>( &self, db: DB, header: &HeaderTy<Self::Primitives>, ) -> EvmFor<Self, DB>

Source§

fn evm_with_env_and_inspector<DB, I>( &self, db: DB, evm_env: EvmEnvFor<Self>, inspector: I, ) -> EvmFor<Self, DB, I>
where DB: Database, I: InspectorFor<Self, DB>,

Source§

fn create_executor<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a,

Source§

fn executor_for_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>

Source§

fn create_block_builder<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, parent: &'a SealedHeader<HeaderTy<Self::Primitives>>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>>
where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a,

Source§

fn builder_for_next_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>, attributes: Self::NextBlockEnvCtx, ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error>

Source§

impl<T: ConfigureEvm + ?Sized> ConfigureEvm for Arc<T>
where Arc<T>: Clone + Debug + Send + Sync + Unpin,

Source§

type Primitives = <T as ConfigureEvm>::Primitives

Source§

type Error = <T as ConfigureEvm>::Error

Source§

type NextBlockEnvCtx = <T as ConfigureEvm>::NextBlockEnvCtx

Source§

type BlockExecutorFactory = <T as ConfigureEvm>::BlockExecutorFactory

Source§

type BlockAssembler = <T as ConfigureEvm>::BlockAssembler

Source§

fn block_executor_factory(&self) -> &Self::BlockExecutorFactory

Source§

fn block_assembler(&self) -> &Self::BlockAssembler

Source§

fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> EvmEnvFor<Self>

Source§

fn next_evm_env( &self, parent: &HeaderTy<Self::Primitives>, attributes: &Self::NextBlockEnvCtx, ) -> Result<EvmEnvFor<Self>, Self::Error>

Source§

fn context_for_block<'a>( &self, block: &'a SealedBlock<BlockTy<Self::Primitives>>, ) -> ExecutionCtxFor<'a, Self>

Source§

fn context_for_next_block( &self, parent: &SealedHeader<HeaderTy<Self::Primitives>>, attributes: Self::NextBlockEnvCtx, ) -> ExecutionCtxFor<'_, Self>

Source§

fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self>

Source§

fn evm_factory(&self) -> &EvmFactoryFor<Self>

Source§

fn evm_with_env<DB: Database>( &self, db: DB, evm_env: EvmEnvFor<Self>, ) -> EvmFor<Self, DB>

Source§

fn evm_for_block<DB: Database>( &self, db: DB, header: &HeaderTy<Self::Primitives>, ) -> EvmFor<Self, DB>

Source§

fn evm_with_env_and_inspector<DB, I>( &self, db: DB, evm_env: EvmEnvFor<Self>, inspector: I, ) -> EvmFor<Self, DB, I>
where DB: Database, I: InspectorFor<Self, DB>,

Source§

fn create_executor<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>
where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a,

Source§

fn executor_for_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>, ) -> impl BlockExecutorFor<'a, Self::BlockExecutorFactory, DB>

Source§

fn create_block_builder<'a, DB, I>( &'a self, evm: EvmFor<Self, &'a mut State<DB>, I>, parent: &'a SealedHeader<HeaderTy<Self::Primitives>>, ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>, ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor: BlockExecutorFor<'a, Self::BlockExecutorFactory, DB, I>>
where DB: Database, I: InspectorFor<Self, &'a mut State<DB>> + 'a,

Source§

fn builder_for_next_block<'a, DB: Database>( &'a self, db: &'a mut State<DB>, parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>, attributes: Self::NextBlockEnvCtx, ) -> Result<impl BlockBuilder<Primitives = Self::Primitives>, Self::Error>

Implementors§