Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions crates/evm/src/block/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Block execution abstraction.

use crate::{Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded, RecoveredTx, ToTxEnv};
use crate::{
Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded, InspectorFor, RecoveredTx,
ToTxEnv,
};
use alloc::{boxed::Box, vec::Vec};
use alloy_consensus::transaction::Recovered;
use alloy_eips::{eip2718::WithEncoded, eip7685::Requests};
Expand All @@ -9,7 +12,6 @@ use revm::{
context_interface::either::Either,
database::State,
inspector::NoOpInspector,
Inspector,
};

mod error;
Expand Down Expand Up @@ -440,22 +442,24 @@ pub trait TxResult {
pub trait BlockExecutorFor<'a, F: BlockExecutorFactory + ?Sized, DB, I = NoOpInspector>
where
Self: BlockExecutor<
Evm = <F::EvmFactory as EvmFactory>::Evm<&'a mut State<DB>, I>,
Evm = <F::EvmFactory as InspectorFor<&'a mut State<DB>, I>>::Evm,
Transaction = F::Transaction,
Receipt = F::Receipt,
>,
DB: Database + 'a,
I: Inspector<<F::EvmFactory as EvmFactory>::Context<&'a mut State<DB>>> + 'a,
F::EvmFactory: InspectorFor<&'a mut State<DB>, I>,
I: 'a,
{
}

impl<'a, F, DB, I, T> BlockExecutorFor<'a, F, DB, I> for T
where
F: BlockExecutorFactory,
DB: Database + 'a,
I: Inspector<<F::EvmFactory as EvmFactory>::Context<&'a mut State<DB>>> + 'a,
F::EvmFactory: InspectorFor<&'a mut State<DB>, I>,
I: 'a,
T: BlockExecutor<
Evm = <F::EvmFactory as EvmFactory>::Evm<&'a mut State<DB>, I>,
Evm = <F::EvmFactory as InspectorFor<&'a mut State<DB>, I>>::Evm,
Transaction = F::Transaction,
Receipt = F::Receipt,
>,
Expand Down Expand Up @@ -579,10 +583,11 @@ pub trait BlockExecutorFactory: 'static {
/// ```
fn create_executor<'a, DB, I>(
&'a self,
evm: <Self::EvmFactory as EvmFactory>::Evm<&'a mut State<DB>, I>,
evm: <Self::EvmFactory as InspectorFor<&'a mut State<DB>, I>>::Evm,
ctx: Self::ExecutionCtx<'a>,
) -> impl BlockExecutorFor<'a, Self, DB, I>
where
DB: Database + 'a,
I: Inspector<<Self::EvmFactory as EvmFactory>::Context<&'a mut State<DB>>> + 'a;
Self::EvmFactory: InspectorFor<&'a mut State<DB>, I>,
I: 'a;
}
9 changes: 5 additions & 4 deletions crates/evm/src/eth/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
BlockExecutorFor, BlockValidationError, ExecutableTx, OnStateHook,
StateChangePostBlockSource, StateChangeSource, SystemCaller, TxResult,
},
Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded, RecoveredTx,
Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded, InspectorFor, RecoveredTx,
};
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
use alloy_consensus::{Header, Transaction, TransactionEnvelope, TxReceipt};
Expand All @@ -24,7 +24,7 @@ use revm::{
context::Block,
context_interface::result::ResultAndState,
database::{DatabaseCommitExt, State},
DatabaseCommit, Inspector,
DatabaseCommit,
};

/// Context for Ethereum block execution.
Expand Down Expand Up @@ -347,12 +347,13 @@ where

fn create_executor<'a, DB, I>(
&'a self,
evm: EvmF::Evm<&'a mut State<DB>, I>,
evm: <EvmF as InspectorFor<&'a mut State<DB>, I>>::Evm,
ctx: Self::ExecutionCtx<'a>,
) -> impl BlockExecutorFor<'a, Self, DB, I>
where
DB: Database + 'a,
I: Inspector<EvmF::Context<&'a mut State<DB>>> + 'a,
EvmF: InspectorFor<&'a mut State<DB>, I>,
I: 'a,
{
EthBlockExecutor::new(evm, ctx, &self.spec, &self.receipt_builder)
}
Expand Down
19 changes: 7 additions & 12 deletions crates/evm/src/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ pub use env::NextEvmEnvAttributes;
#[cfg(feature = "op")]
pub(crate) use env::EvmEnvInput;

use crate::{env::EvmEnv, evm::EvmFactory, precompiles::PrecompilesMap, Database, Evm};
use crate::{
env::EvmEnv, evm::EvmFactory, precompiles::PrecompilesMap, Database, Evm, InspectorFor,
};
use alloy_primitives::{Address, Bytes};
use core::{
fmt::Debug,
Expand Down Expand Up @@ -267,25 +269,18 @@ where
pub struct EthEvmFactory;

impl EvmFactory for EthEvmFactory {
type Evm<DB: Database, I: Inspector<EthEvmContext<DB>>> = EthEvm<DB, I, Self::Precompiles>;
type Context<DB: Database> = Context<BlockEnv, TxEnv, CfgEnv, DB>;
type Tx = TxEnv;
type Error<DBError: core::error::Error + Send + Sync + 'static> = EVMError<DBError>;
type HaltReason = HaltReason;
type Spec = SpecId;
type BlockEnv = BlockEnv;
type Precompiles = PrecompilesMap;
}

fn create_evm<DB: Database>(&self, db: DB, input: EvmEnv) -> Self::Evm<DB, NoOpInspector> {
EthEvmBuilder::new(db, input).build()
}
impl<DB: Database, I: Inspector<EthEvmContext<DB>>> InspectorFor<DB, I> for EthEvmFactory {
type Evm = EthEvm<DB, I, PrecompilesMap>;

fn create_evm_with_inspector<DB: Database, I: Inspector<Self::Context<DB>>>(
&self,
db: DB,
input: EvmEnv,
inspector: I,
) -> Self::Evm<DB, I> {
fn create_evm_with_inspector(&self, db: DB, input: EvmEnv, inspector: I) -> Self::Evm {
EthEvmBuilder::new(db, input).activate_inspector(inspector).build()
}
}
Expand Down
71 changes: 45 additions & 26 deletions crates/evm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ use alloy_primitives::{Address, Bytes, B256};
use core::{error::Error, fmt::Debug, hash::Hash};
use revm::{
context::result::ExecutionResult,
context_interface::{
result::{HaltReasonTr, ResultAndState},
ContextTr,
},
inspector::{JournalExt, NoOpInspector},
DatabaseCommit, Inspector,
context_interface::result::{HaltReasonTr, ResultAndState},
inspector::NoOpInspector,
DatabaseCommit,
};

/// Helper trait to bound [`revm::Database::Error`] with common requirements.
Expand Down Expand Up @@ -254,20 +251,6 @@ impl<T: Evm> EvmExt for T {}

/// A type responsible for creating instances of an ethereum virtual machine given a certain input.
pub trait EvmFactory {
/// The EVM type that this factory creates.
type Evm<DB: Database, I: Inspector<Self::Context<DB>>>: Evm<
DB = DB,
Tx = Self::Tx,
HaltReason = Self::HaltReason,
Error = Self::Error<DB::Error>,
Spec = Self::Spec,
BlockEnv = Self::BlockEnv,
Precompiles = Self::Precompiles,
Inspector = I,
>;

/// The EVM context for inspectors
type Context<DB: Database>: ContextTr<Db = DB, Journal: JournalExt>;
/// Transaction environment.
type Tx: IntoTxEnv<Self::Tx>;
/// EVM error. See [`Evm::Error`].
Expand All @@ -282,22 +265,57 @@ pub trait EvmFactory {
type Precompiles;

/// Creates a new instance of an EVM.
///
/// Default implementation delegates to
/// [`InspectorFor::create_evm_with_inspector`] with a [`NoOpInspector`].
fn create_evm<DB: Database>(
&self,
db: DB,
evm_env: EvmEnv<Self::Spec, Self::BlockEnv>,
) -> Self::Evm<DB, NoOpInspector>;
) -> <Self as InspectorFor<DB, NoOpInspector>>::Evm
where
Self: InspectorFor<DB, NoOpInspector>,
{
self.create_evm_with_inspector(db, evm_env, NoOpInspector)
}
}

/// Defines inspector compatibility for an [`EvmFactory`].
///
/// This trait is implemented by [`EvmFactory`] types to declare which inspector types
/// they accept for a given database type, and to provide EVM construction with that inspector.
///
/// For single-context EVM factories (like [`EthEvmFactory`](crate::EthEvmFactory)), this is
/// typically blanket-implemented for any `I: Inspector<Context<DB>>`.
///
/// For multi-context EVM factories (like enum dispatchers wrapping multiple EVM variants),
/// this can require `I` to implement [`Inspector`] for multiple context types, enabling
/// generic support for enum-based EVMs without modifying these traits.
///
/// [`EthEvmFactory`]: crate::EthEvmFactory
pub trait InspectorFor<DB: Database, I>: EvmFactory {
/// The EVM type produced by this factory for the given database and inspector.
type Evm: Evm<
DB = DB,
Tx = <Self as EvmFactory>::Tx,
HaltReason = <Self as EvmFactory>::HaltReason,
Error = <Self as EvmFactory>::Error<DB::Error>,
Spec = <Self as EvmFactory>::Spec,
BlockEnv = <Self as EvmFactory>::BlockEnv,
Precompiles = <Self as EvmFactory>::Precompiles,
Inspector = I,
Comment on lines +298 to +306

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there's no other way than type erasure to implement Foundry's EitherEvm. The question is whether we're going to keep this pattern.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it serves as a good bridge for eventually removing it in the future but i think we should keep it now

>;

/// Creates a new instance of an EVM with an inspector.
///
/// Note: It is expected that the [`Inspector`] is usually provided as `&mut Inspector` so that
/// it remains owned by the call site when [`Evm::transact`] is invoked.
fn create_evm_with_inspector<DB: Database, I: Inspector<Self::Context<DB>>>(
fn create_evm_with_inspector(
&self,
db: DB,
input: EvmEnv<Self::Spec, Self::BlockEnv>,
input: EvmEnv<<Self as EvmFactory>::Spec, <Self as EvmFactory>::BlockEnv>,
inspector: I,
) -> Self::Evm<DB, I>;
) -> Self::Evm;
}

/// An extension trait for [`EvmFactory`] providing useful non-overridable methods.
Expand All @@ -308,10 +326,11 @@ pub trait EvmFactoryExt: EvmFactory {
db: DB,
input: EvmEnv<Self::Spec, Self::BlockEnv>,
fused_inspector: I,
) -> TxTracer<Self::Evm<DB, I>>
) -> TxTracer<<Self as InspectorFor<DB, I>>::Evm>
where
DB: Database + DatabaseCommit,
I: Inspector<Self::Context<DB>> + Clone,
Self: InspectorFor<DB, I>,
I: Clone,
{
TxTracer::new(self.create_evm_with_inspector(db, input, fused_inspector))
}
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern crate alloc;

pub mod block;
pub mod evm;
pub use evm::{Database, Evm, EvmFactory};
pub use evm::{Database, Evm, EvmFactory, InspectorFor};
pub mod eth;
pub use eth::{EthEvm, EthEvmFactory};
pub mod env;
Expand Down
Loading