reth_evm/lib.rs
1//! Traits for configuring an EVM specifics.
2//!
3//! # Revm features
4//!
5//! This crate does __not__ enforce specific revm features such as `blst` or `c-kzg`, which are
6//! critical for revm's evm internals, it is the responsibility of the implementer to ensure the
7//! proper features are selected.
8
9#![doc(
10 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
11 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
12 issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
13)]
14#![cfg_attr(not(test), warn(unused_crate_dependencies))]
15#![cfg_attr(docsrs, feature(doc_cfg))]
16#![cfg_attr(not(feature = "std"), no_std)]
17
18extern crate alloc;
19
20use crate::execute::{BasicBlockBuilder, Executor};
21use alloc::{string::String, vec::Vec};
22use alloy_eips::eip4895::Withdrawals;
23use alloy_evm::{
24 block::{BlockExecutorFactory, BlockExecutorFor},
25 precompiles::PrecompilesMap,
26};
27use alloy_primitives::{Address, Bytes, B256};
28use core::{error::Error, fmt::Debug};
29use execute::{BasicBlockExecutor, BlockAssembler, BlockBuilder};
30use reth_execution_errors::BlockExecutionError;
31use reth_primitives_traits::{
32 BlockTy, HeaderTy, NodePrimitives, ReceiptTy, SealedBlock, SealedHeader, TxTy,
33};
34use revm::{database::State, primitives::hardfork::SpecId};
35
36pub mod either;
37/// EVM environment configuration.
38pub mod execute;
39
40mod aliases;
41pub use aliases::*;
42
43#[cfg(feature = "std")]
44mod engine;
45#[cfg(feature = "std")]
46pub use engine::{ConfigureEngineEvm, ConvertTx, ExecutableTxIterator, ExecutableTxTuple};
47mod sender_recovery;
48pub use sender_recovery::SenderRecoveryCache;
49
50#[cfg(feature = "metrics")]
51pub mod metrics;
52pub mod noop;
53#[cfg(any(test, feature = "test-utils"))]
54/// test helpers for mocking executor
55pub mod test_utils;
56
57pub use alloy_evm::{
58 block::{state_changes, system_calls, OnStateHook},
59 *,
60};
61
62/// A complete configuration of EVM for Reth.
63///
64/// This trait encapsulates complete configuration required for transaction execution and block
65/// execution/building, providing a unified interface for EVM operations.
66///
67/// # Architecture Overview
68///
69/// The EVM abstraction consists of the following layers:
70///
71/// 1. **[`Evm`] (produced by [`EvmFactory`])**: The core EVM implementation responsible for
72/// executing individual transactions and producing outputs including state changes, logs, gas
73/// usage, etc.
74///
75/// 2. **[`BlockExecutor`] (produced by [`BlockExecutorFactory`])**: A higher-level component that
76/// operates on top of [`Evm`] to execute entire blocks. This involves:
77/// - Executing all transactions in sequence
78/// - Building receipts from transaction outputs
79/// - Applying block rewards to the beneficiary
80/// - Executing system calls (e.g., EIP-4788 beacon root updates)
81/// - Managing state changes and bundle accumulation
82///
83/// 3. **[`BlockAssembler`]**: Responsible for assembling valid blocks from executed transactions.
84/// It takes the output from [`BlockExecutor`] along with execution context and produces a
85/// complete block ready for inclusion in the chain.
86///
87/// # Usage Patterns
88///
89/// The abstraction supports two primary use cases:
90///
91/// ## 1. Executing Externally Provided Blocks (e.g., during sync)
92///
93/// ```rust,ignore
94/// use reth_evm::ConfigureEvm;
95///
96/// // Execute a received block
97/// let mut executor = evm_config.executor(state_db);
98/// let output = executor.execute(&block)?;
99///
100/// // Access the execution results
101/// println!("Gas used: {}", output.result.gas_used);
102/// println!("Receipts: {:?}", output.result.receipts);
103/// ```
104///
105/// ## 2. Building New Blocks (e.g., payload building)
106///
107/// Payload building is slightly different as it doesn't have the block's header yet, but rather
108/// attributes for the block's environment, such as timestamp, fee recipient, and randomness value.
109/// The block's header will be the outcome of the block building process.
110///
111/// ```rust,ignore
112/// use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};
113///
114/// // Create attributes for the next block
115/// let attributes = NextBlockEnvAttributes {
116/// timestamp: current_time + 12,
117/// suggested_fee_recipient: beneficiary_address,
118/// prev_randao: randomness_value,
119/// gas_limit: 30_000_000,
120/// withdrawals: Some(withdrawals),
121/// parent_beacon_block_root: Some(beacon_root),
122/// slot_number: None,
123/// };
124///
125/// // Build a new block on top of parent
126/// let mut builder = evm_config.builder_for_next_block(
127/// &mut state_db,
128/// &parent_header,
129/// attributes
130/// )?;
131///
132/// // Apply pre-execution changes (e.g., beacon root update)
133/// builder.apply_pre_execution_changes()?;
134///
135/// // Execute transactions
136/// for tx in pending_transactions {
137/// match builder.execute_transaction(tx) {
138/// Ok(gas_used) => {
139/// println!("Transaction executed, gas used: {}", gas_used);
140/// }
141/// Err(e) => {
142/// println!("Transaction failed: {:?}", e);
143/// }
144/// }
145/// }
146///
147/// // Finish block building and get the outcome (block)
148/// let outcome = builder.finish(state_provider, None)?;
149/// let block = outcome.block;
150/// ```
151///
152/// # Key Components
153///
154/// ## [`NextBlockEnvCtx`]
155///
156/// Contains attributes needed to configure the next block that cannot be derived from the
157/// parent block alone. This includes data typically provided by the consensus layer:
158/// - `timestamp`: Block timestamp
159/// - `suggested_fee_recipient`: Beneficiary address
160/// - `prev_randao`: Randomness value
161/// - `gas_limit`: Block gas limit
162/// - `withdrawals`: Consensus layer withdrawals
163/// - `parent_beacon_block_root`: EIP-4788 beacon root
164///
165/// ## [`BlockAssembler`]
166///
167/// Takes the execution output and produces a complete block. It receives:
168/// - Transaction execution results (receipts, gas used)
169/// - Final state root after all executions
170/// - Bundle state with all changes
171/// - Execution context and environment
172///
173/// The assembler is responsible for:
174/// - Setting the correct block header fields
175/// - Including executed transactions
176/// - Setting gas used and receipts root
177/// - Applying any chain-specific rules
178///
179/// [`ExecutionCtx`]: BlockExecutorFactory::ExecutionCtx
180/// [`NextBlockEnvCtx`]: ConfigureEvm::NextBlockEnvCtx
181/// [`BlockExecutor`]: alloy_evm::block::BlockExecutor
182#[auto_impl::auto_impl(&, Arc)]
183pub trait ConfigureEvm: Clone + Debug + Send + Sync + Unpin {
184 /// The primitives type used by the EVM.
185 type Primitives: NodePrimitives;
186
187 /// The error type that is returned by [`Self::next_evm_env`].
188 type Error: Error + Send + Sync + 'static;
189
190 /// Context required for configuring next block environment.
191 ///
192 /// Contains values that can't be derived from the parent block.
193 type NextBlockEnvCtx: Debug + Clone;
194
195 /// Configured [`BlockExecutorFactory`], contains [`EvmFactory`] internally.
196 type BlockExecutorFactory: for<'a> BlockExecutorFactory<
197 Transaction = TxTy<Self::Primitives>,
198 Receipt = ReceiptTy<Self::Primitives>,
199 ExecutionCtx<'a>: Debug + Send,
200 EvmFactory: EvmFactory<
201 Tx: TransactionEnvMut
202 + FromRecoveredTx<TxTy<Self::Primitives>>
203 + FromTxWithEncoded<TxTy<Self::Primitives>>,
204 Precompiles = PrecompilesMap,
205 Spec: Into<SpecId>,
206 >,
207 >;
208
209 /// A type that knows how to build a block.
210 type BlockAssembler: BlockAssembler<
211 Self::BlockExecutorFactory,
212 Block = BlockTy<Self::Primitives>,
213 >;
214
215 /// Returns reference to the configured [`BlockExecutorFactory`].
216 fn block_executor_factory(&self) -> &Self::BlockExecutorFactory;
217
218 /// Returns reference to the configured [`BlockAssembler`].
219 fn block_assembler(&self) -> &Self::BlockAssembler;
220
221 /// Creates a new [`EvmEnv`] for the given header.
222 fn evm_env(&self, header: &HeaderTy<Self::Primitives>) -> Result<EvmEnvFor<Self>, Self::Error>;
223
224 /// Returns the configured [`EvmEnv`] for `parent + 1` block.
225 ///
226 /// This is intended for usage in block building after the merge and requires additional
227 /// attributes that can't be derived from the parent block: attributes that are determined by
228 /// the CL, such as the timestamp, suggested fee recipient, and randomness value.
229 ///
230 /// # Example
231 ///
232 /// ```rust,ignore
233 /// let evm_env = evm_config.next_evm_env(&parent_header, &attributes)?;
234 /// // evm_env now contains:
235 /// // - Correct spec ID based on timestamp and block number
236 /// // - Block environment with next block's parameters
237 /// // - Configuration like chain ID and blob parameters
238 /// ```
239 fn next_evm_env(
240 &self,
241 parent: &HeaderTy<Self::Primitives>,
242 attributes: &Self::NextBlockEnvCtx,
243 ) -> Result<EvmEnvFor<Self>, Self::Error>;
244
245 /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for a given block.
246 fn context_for_block<'a>(
247 &self,
248 block: &'a SealedBlock<BlockTy<Self::Primitives>>,
249 ) -> Result<ExecutionCtxFor<'a, Self>, Self::Error>;
250
251 /// Returns the configured [`BlockExecutorFactory::ExecutionCtx`] for `parent + 1`
252 /// block.
253 fn context_for_next_block(
254 &self,
255 parent: &SealedHeader<HeaderTy<Self::Primitives>>,
256 attributes: Self::NextBlockEnvCtx,
257 ) -> Result<ExecutionCtxFor<'_, Self>, Self::Error>;
258
259 /// Returns a [`EvmFactory::Tx`] from a transaction.
260 fn tx_env(&self, transaction: impl IntoTxEnv<TxEnvFor<Self>>) -> TxEnvFor<Self> {
261 transaction.into_tx_env()
262 }
263
264 /// Provides a reference to [`EvmFactory`] implementation.
265 fn evm_factory(&self) -> &EvmFactoryFor<Self> {
266 self.block_executor_factory().evm_factory()
267 }
268
269 /// Returns a config with JIT support enabled for subsequently created EVMs, if supported.
270 ///
271 /// This is one of three gates required before an EVM can execute JIT-compiled code: the binary
272 /// must be built with the `jit` feature, runtime compilation must be enabled by `--jit` or the
273 /// `reth_jit` RPC method, and this local support flag must be enabled for the config that
274 /// creates the EVM.
275 #[auto_impl(keep_default_for(&, Arc))]
276 fn with_jit_support_enabled(self, _enabled: bool) -> Self
277 where
278 Self: Sized,
279 {
280 self
281 }
282
283 /// Returns a config with local JIT support enabled for subsequently created EVMs, if supported.
284 #[auto_impl(keep_default_for(&, Arc))]
285 fn with_jit_support(self) -> Self
286 where
287 Self: Sized,
288 {
289 self.with_jit_support_enabled(true)
290 }
291
292 /// Returns the JIT backend, if supported.
293 fn jit_backend(&self) -> Option<&dyn JitBackend> {
294 None
295 }
296
297 /// Returns a new EVM with the given database configured with the given environment settings,
298 /// including the spec id and transaction environment.
299 ///
300 /// This will preserve any handler modifications
301 fn evm_with_env<DB: Database>(&self, db: DB, evm_env: EvmEnvFor<Self>) -> EvmFor<Self, DB> {
302 self.evm_factory().create_evm(db, evm_env)
303 }
304
305 /// Returns a new EVM with the given database configured with `cfg` and `block_env`
306 /// configuration derived from the given header. Relies on
307 /// [`ConfigureEvm::evm_env`].
308 ///
309 /// # Caution
310 ///
311 /// This does not initialize the tx environment.
312 fn evm_for_block<DB: Database>(
313 &self,
314 db: DB,
315 header: &HeaderTy<Self::Primitives>,
316 ) -> Result<EvmFor<Self, DB>, Self::Error> {
317 let evm_env = self.evm_env(header)?;
318 Ok(self.evm_with_env(db, evm_env))
319 }
320
321 /// Returns a new EVM with the given database configured with the given environment settings,
322 /// including the spec id.
323 ///
324 /// This will use the given external inspector as the EVM external context.
325 ///
326 /// This will preserve any handler modifications
327 fn evm_with_env_and_inspector<DB, I>(
328 &self,
329 db: DB,
330 evm_env: EvmEnvFor<Self>,
331 inspector: I,
332 ) -> EvmFor<Self, DB, I>
333 where
334 DB: Database,
335 I: InspectorFor<Self, DB>,
336 {
337 self.evm_factory().create_evm_with_inspector(db, evm_env, inspector)
338 }
339
340 /// Creates a strategy with given EVM and execution context.
341 fn create_executor<'a, DB, I>(
342 &'a self,
343 evm: EvmFor<Self, &'a mut State<DB>, I>,
344 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
345 ) -> BlockExecutorForEvm<'a, Self, DB, I>
346 where
347 DB: Database,
348 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
349 {
350 self.block_executor_factory().create_executor(evm, ctx)
351 }
352
353 /// Creates a strategy with a DB state borrow that can be shorter than the execution context.
354 fn create_executor_with_state<'a, 'db, DB, I>(
355 &'a self,
356 evm: EvmFor<Self, &'db mut State<DB>, I>,
357 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
358 ) -> BlockExecutorFor<'a, Self::BlockExecutorFactory, &'db mut State<DB>, I>
359 where
360 DB: Database,
361 I: InspectorFor<Self, &'db mut State<DB>>,
362 {
363 self.block_executor_factory().create_executor(evm, ctx)
364 }
365
366 /// Creates a strategy for execution of a given block.
367 fn executor_for_block<'a, DB: Database>(
368 &'a self,
369 db: &'a mut State<DB>,
370 block: &'a SealedBlock<<Self::Primitives as NodePrimitives>::Block>,
371 ) -> Result<BlockExecutorForEvm<'a, Self, DB>, Self::Error> {
372 let evm = self.evm_for_block(db, block.header())?;
373 let ctx = self.context_for_block(block)?;
374 Ok(self.create_executor(evm, ctx))
375 }
376
377 /// Creates a [`BlockBuilder`]. Should be used when building a new block.
378 ///
379 /// Block builder wraps an inner [`alloy_evm::block::BlockExecutor`] and has a similar
380 /// interface. Builder collects all of the executed transactions, and once
381 /// [`BlockBuilder::finish`] is called, it invokes the configured [`BlockAssembler`] to
382 /// create a block.
383 ///
384 /// # Example
385 ///
386 /// ```rust,ignore
387 /// // Create a builder with specific EVM configuration
388 /// let evm = evm_config.evm_with_env(&mut state_db, evm_env);
389 /// let ctx = evm_config.context_for_next_block(&parent, attributes);
390 /// let builder = evm_config.create_block_builder(evm, &parent, ctx);
391 /// ```
392 fn create_block_builder<'a, DB, I>(
393 &'a self,
394 evm: EvmFor<Self, &'a mut State<DB>, I>,
395 parent: &'a SealedHeader<HeaderTy<Self::Primitives>>,
396 ctx: <Self::BlockExecutorFactory as BlockExecutorFactory>::ExecutionCtx<'a>,
397 ) -> impl BlockBuilder<Primitives = Self::Primitives, Executor = BlockExecutorForEvm<'a, Self, DB, I>>
398 where
399 DB: Database,
400 I: InspectorFor<Self, &'a mut State<DB>> + 'a,
401 {
402 BasicBlockBuilder {
403 executor: self.create_executor(evm, ctx.clone()),
404 ctx,
405 assembler: self.block_assembler(),
406 parent,
407 transactions: Vec::new(),
408 }
409 }
410
411 /// Creates a [`BlockBuilder`] for building of a new block. This is a helper to invoke
412 /// [`ConfigureEvm::create_block_builder`].
413 ///
414 /// This is the primary method for building new blocks. It combines:
415 /// 1. Creating the EVM environment for the next block
416 /// 2. Setting up the execution context from attributes
417 /// 3. Initializing the block builder with proper configuration
418 ///
419 /// # Example
420 ///
421 /// ```rust,ignore
422 /// // Build a block with specific attributes
423 /// let mut builder = evm_config.builder_for_next_block(
424 /// &mut state_db,
425 /// &parent_header,
426 /// attributes
427 /// )?;
428 ///
429 /// // Execute system calls (e.g., beacon root update)
430 /// builder.apply_pre_execution_changes()?;
431 ///
432 /// // Execute transactions
433 /// for tx in transactions {
434 /// builder.execute_transaction(tx)?;
435 /// }
436 ///
437 /// // Complete block building
438 /// let outcome = builder.finish(state_provider, None)?;
439 /// ```
440 fn builder_for_next_block<'a, DB: Database + 'a>(
441 &'a self,
442 db: &'a mut State<DB>,
443 parent: &'a SealedHeader<<Self::Primitives as NodePrimitives>::BlockHeader>,
444 attributes: Self::NextBlockEnvCtx,
445 ) -> Result<
446 impl BlockBuilder<Primitives = Self::Primitives, Executor = BlockExecutorForEvm<'a, Self, DB>>,
447 Self::Error,
448 > {
449 let evm_env = self.next_evm_env(parent, &attributes)?;
450 let evm = self.evm_with_env(db, evm_env);
451 let ctx = self.context_for_next_block(parent, attributes)?;
452 Ok(self.create_block_builder(evm, parent, ctx))
453 }
454
455 /// Returns a new [`Executor`] for executing blocks.
456 ///
457 /// The executor processes complete blocks including:
458 /// - All transactions in order
459 /// - Block rewards and fees
460 /// - Block level system calls
461 /// - State transitions
462 ///
463 /// # Example
464 ///
465 /// ```rust,ignore
466 /// // Create an executor
467 /// let mut executor = evm_config.executor(state_db);
468 ///
469 /// // Execute a single block
470 /// let output = executor.execute(&block)?;
471 ///
472 /// // Execute multiple blocks
473 /// let batch_output = executor.execute_batch(&blocks)?;
474 /// ```
475 #[auto_impl(keep_default_for(&, Arc))]
476 fn executor<DB: Database>(
477 &self,
478 db: DB,
479 ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> {
480 BasicBlockExecutor::new(self, db)
481 }
482
483 /// Returns a new [`BasicBlockExecutor`].
484 #[auto_impl(keep_default_for(&, Arc))]
485 fn batch_executor<DB: Database>(
486 &self,
487 db: DB,
488 ) -> impl Executor<DB, Primitives = Self::Primitives, Error = BlockExecutionError> {
489 BasicBlockExecutor::new(self, db)
490 }
491}
492
493/// JIT backend controls exposed by an EVM configuration.
494pub trait JitBackend: Send + Sync {
495 /// Enables or disables JIT compilation.
496 fn set_enabled(&self, enabled: bool) -> Result<(), String>;
497
498 /// Pauses JIT helper execution while keeping queueing and resident compiled code available.
499 fn pause(&self);
500
501 /// Resumes background JIT work.
502 fn resume(&self);
503
504 /// Clears JIT runtime state.
505 fn clear(&self);
506}
507
508/// Represents additional attributes required to configure the next block.
509///
510/// This struct contains all the information needed to build a new block that cannot be
511/// derived from the parent block header alone. These attributes are typically provided
512/// by the consensus layer (CL) through the Engine API during payload building.
513///
514/// # Relationship with [`ConfigureEvm`] and [`BlockAssembler`]
515///
516/// The flow for building a new block involves:
517///
518/// 1. **Receive attributes** from the consensus layer containing:
519/// - Timestamp for the new block
520/// - Fee recipient (coinbase/beneficiary)
521/// - Randomness value (prevRandao)
522/// - Withdrawals to process
523/// - Parent beacon block root for EIP-4788
524///
525/// 2. **Configure EVM environment** using these attributes: ```rust,ignore let evm_env =
526/// evm_config.next_evm_env(&parent, &attributes)?; ```
527///
528/// 3. **Build the block** with transactions: ```rust,ignore let mut builder =
529/// evm_config.builder_for_next_block( &mut state, &parent, attributes )?; ```
530///
531/// 4. **Assemble the final block** using [`BlockAssembler`] which takes:
532/// - Execution results from all transactions
533/// - The attributes used during execution
534/// - Final state root after all changes
535///
536/// This design cleanly separates:
537/// - **Configuration** (what parameters to use) - handled by `NextBlockEnvAttributes`
538/// - **Execution** (running transactions) - handled by `BlockExecutor`
539/// - **Assembly** (creating the final block) - handled by `BlockAssembler`
540#[derive(Debug, Clone, PartialEq, Eq)]
541pub struct NextBlockEnvAttributes {
542 /// The timestamp of the next block.
543 pub timestamp: u64,
544 /// The suggested fee recipient for the next block.
545 pub suggested_fee_recipient: Address,
546 /// The randomness value for the next block.
547 pub prev_randao: B256,
548 /// Block gas limit.
549 pub gas_limit: u64,
550 /// The parent beacon block root.
551 pub parent_beacon_block_root: Option<B256>,
552 /// Withdrawals
553 pub withdrawals: Option<Withdrawals>,
554 /// Optional extra data.
555 pub extra_data: Bytes,
556 /// Optional slot number for post-Amsterdam payloads.
557 pub slot_number: Option<u64>,
558}