use alloy_consensus::{Transaction, TxReceipt};
use alloy_eips::Encodable2718;
use alloy_evm::{
block::BlockExecutorFor, Database, EvmEnv, EvmFactory, FromRecoveredTx, FromTxWithEncoded,
};
use alloy_op_evm::block::receipt_builder::OpReceiptBuilder;
use alloy_primitives::{Bytes, B256};
use revm::{database::State, inspector::NoOpInspector, Inspector};
use crate::{BlockLimits, MegaBlockExecutor, MegaEvm, MegaHardforks, MegaSpecId, MegaTxEnvelope};
#[derive(Debug, Clone)]
pub struct MegaBlockExecutorFactory<Hardforks, EvmF, ReceiptBuilder> {
receipt_builder: ReceiptBuilder,
hardforks: Hardforks,
evm_factory: EvmF,
}
impl<Hardforks, EvmF, ReceiptBuilder> MegaBlockExecutorFactory<Hardforks, EvmF, ReceiptBuilder>
where
ReceiptBuilder: OpReceiptBuilder,
{
pub fn new(hardforks: Hardforks, evm_factory: EvmF, receipt_builder: ReceiptBuilder) -> Self {
Self { receipt_builder, hardforks, evm_factory }
}
pub fn evm_factory_ref(&self) -> &EvmF {
&self.evm_factory
}
pub fn evm_factory_mut(&mut self) -> &mut EvmF {
&mut self.evm_factory
}
}
impl<Hardforks, ExtEnvFactory, ReceiptBuilder>
MegaBlockExecutorFactory<Hardforks, crate::MegaEvmFactory<ExtEnvFactory>, ReceiptBuilder>
where
Hardforks: MegaHardforks + Clone,
ReceiptBuilder: OpReceiptBuilder<Transaction: Transaction + Encodable2718> + Clone,
crate::MegaTransaction: FromRecoveredTx<ReceiptBuilder::Transaction>,
ExtEnvFactory: crate::ExternalEnvFactory + Clone,
{
pub fn create_executor<'a, DB>(
&self,
db: &'a mut State<DB>,
block_ctx: MegaBlockExecutionCtx,
evm_env: EvmEnv<MegaSpecId>,
) -> MegaBlockExecutor<
Hardforks,
MegaEvm<&'a mut State<DB>, NoOpInspector, ExtEnvFactory::EnvTypes>,
ReceiptBuilder,
>
where
DB: Database + 'a,
{
let runtime_limits = block_ctx.block_limits.to_evm_tx_runtime_limits();
let evm = self.evm_factory.create_evm(db, evm_env).with_tx_runtime_limits(runtime_limits);
MegaBlockExecutor::new(evm, block_ctx, self.hardforks.clone(), self.receipt_builder.clone())
}
pub fn create_executor_with_inspector<'a, DB, I>(
&self,
db: &'a mut State<DB>,
block_ctx: MegaBlockExecutionCtx,
evm_env: EvmEnv<MegaSpecId>,
inspector: I,
) -> MegaBlockExecutor<
Hardforks,
MegaEvm<&'a mut State<DB>, I, ExtEnvFactory::EnvTypes>,
ReceiptBuilder,
>
where
DB: Database + 'a,
I: Inspector<crate::MegaContext<&'a mut State<DB>, ExtEnvFactory::EnvTypes>> + 'a,
{
let runtime_limits = block_ctx.block_limits.to_evm_tx_runtime_limits();
let evm = self
.evm_factory
.create_evm_with_inspector(db, evm_env, inspector)
.with_tx_runtime_limits(runtime_limits);
MegaBlockExecutor::new(evm, block_ctx, self.hardforks.clone(), self.receipt_builder.clone())
}
}
impl<Hardforks, ExtEnvFactory, ReceiptBuilder> alloy_evm::block::BlockExecutorFactory
for MegaBlockExecutorFactory<Hardforks, crate::MegaEvmFactory<ExtEnvFactory>, ReceiptBuilder>
where
ReceiptBuilder: OpReceiptBuilder<Transaction = MegaTxEnvelope, Receipt: TxReceipt>,
Hardforks: MegaHardforks + Clone,
ExtEnvFactory: crate::ExternalEnvFactory + Clone,
crate::MegaTransaction: FromRecoveredTx<ReceiptBuilder::Transaction>
+ FromTxWithEncoded<ReceiptBuilder::Transaction>,
Self: 'static,
{
type EvmFactory = crate::MegaEvmFactory<ExtEnvFactory>;
type ExecutionCtx<'a> = MegaBlockExecutionCtx;
type Transaction = ReceiptBuilder::Transaction;
type Receipt = ReceiptBuilder::Receipt;
fn evm_factory(&self) -> &Self::EvmFactory {
self.evm_factory_ref()
}
fn create_executor<'a, DB, I>(
&'a self,
evm: <Self::EvmFactory as alloy_evm::EvmFactory>::Evm<&'a mut State<DB>, I>,
ctx: Self::ExecutionCtx<'a>,
) -> impl BlockExecutorFor<'a, Self, DB, I>
where
DB: Database + 'a,
I: Inspector<<Self::EvmFactory as alloy_evm::EvmFactory>::Context<&'a mut State<DB>>> + 'a,
{
let runtime_limits = ctx.block_limits.to_evm_tx_runtime_limits();
let evm = evm.with_tx_runtime_limits(runtime_limits);
MegaBlockExecutor::new(evm, ctx, &self.hardforks, &self.receipt_builder)
}
}
#[derive(Debug, Clone)]
pub struct MegaBlockExecutionCtx {
pub parent_hash: B256,
pub parent_beacon_block_root: Option<B256>,
pub extra_data: Bytes,
pub block_limits: BlockLimits,
}
impl MegaBlockExecutionCtx {
pub fn new(
parent_hash: B256,
parent_beacon_block_root: Option<B256>,
extra_data: Bytes,
block_limits: BlockLimits,
) -> Self {
Self { parent_hash, parent_beacon_block_root, extra_data, block_limits }
}
}