Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions bin/client/src/kona.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ fn main() -> Result<()> {
let OptimismAttributesWithParent { attributes, .. } =
driver.produce_disputed_payload().await?;

let mut executor = StatelessL2BlockExecutor::builder(&boot.rollup_config)
.with_parent_header(driver.take_l2_safe_head_header())
.with_provider(l2_provider.clone())
.with_hinter(l2_provider)
.with_handle_register(fpvm_handle_register)
.build()?;
let mut executor = StatelessL2BlockExecutor::builder(
&boot.rollup_config,
l2_provider.clone(),
l2_provider,
)
.with_parent_header(driver.take_l2_safe_head_header())
.with_handle_register(fpvm_handle_register)
.build();
let Header { number, .. } = *executor.execute_payload(attributes)?;
let output_root = executor.compute_output_root()?;

Expand Down
3 changes: 2 additions & 1 deletion crates/executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ homepage.workspace = true

[dependencies]
# General
anyhow.workspace = true
thiserror.workspace = true
tracing.workspace = true
alloy-primitives = { workspace = true, features = ["rlp"] }
alloy-eips.workspace = true
Expand All @@ -24,6 +24,7 @@ revm = { workspace = true, features = ["optimism"] }
kona-mpt.workspace = true

[dev-dependencies]
anyhow.workspace = true
alloy-rlp.workspace = true
serde.workspace = true
serde_json.workspace = true
Expand Down
13 changes: 7 additions & 6 deletions crates/executor/benches/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,13 @@ fn op_mainnet_exec_bench(

// Bench the block execution.
bencher.iter(|| {
let mut l2_block_executor = StatelessL2BlockExecutor::builder(&rollup_config)
.with_parent_header(pre_state_header.clone().seal_slow())
.with_provider(TestdataTrieProvider::new(data_folder))
.with_hinter(NoopTrieHinter)
.build()
.unwrap();
let mut l2_block_executor = StatelessL2BlockExecutor::builder(
&rollup_config,
TestdataTrieProvider::new(data_folder),
NoopTrieHinter,
)
.with_parent_header(pre_state_header.clone().seal_slow())
.build();
l2_block_executor.execute_payload(payload_attrs.clone()).unwrap();
});
}
Expand Down
36 changes: 11 additions & 25 deletions crates/executor/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use crate::StatelessL2BlockExecutor;
use alloy_consensus::{Header, Sealable, Sealed};
use anyhow::Result;
use kona_mpt::{TrieDB, TrieHinter, TrieProvider};
use op_alloy_genesis::RollupConfig;
use revm::{db::State, handler::register::EvmHandler};
Expand All @@ -20,14 +19,14 @@ where
{
/// The [RollupConfig].
config: &'a RollupConfig,
/// The [TrieProvider] to fetch the state trie preimages.
provider: F,
/// The [TrieHinter] to hint the state trie preimages.
hinter: H,
/// The parent [Header] to begin execution from.
parent_header: Option<Sealed<Header>>,
/// The [KonaHandleRegister] to use during execution.
handler_register: Option<KonaHandleRegister<F, H>>,
/// The [TrieProvider] to fetch the state trie preimages.
fetcher: Option<F>,
/// The [TrieHinter] to hint the state trie preimages.
hinter: Option<H>,
}

impl<'a, F, H> StatelessL2BlockExecutorBuilder<'a, F, H>
Expand All @@ -36,8 +35,8 @@ where
H: TrieHinter,
{
/// Instantiate a new builder with the given [RollupConfig].
pub fn with_config(config: &'a RollupConfig) -> Self {
Self { config, parent_header: None, handler_register: None, fetcher: None, hinter: None }
pub fn new(config: &'a RollupConfig, provider: F, hinter: H) -> Self {
Self { config, provider, hinter, parent_header: None, handler_register: None }
}

/// Set the [Header] to begin execution from.
Expand All @@ -46,38 +45,25 @@ where
self
}

/// Set the [TrieProvider] to fetch the state trie preimages.
pub fn with_provider(mut self, fetcher: F) -> Self {
self.fetcher = Some(fetcher);
self
}

/// Set the [TrieHinter] to hint the state trie preimages.
pub fn with_hinter(mut self, hinter: H) -> Self {
self.hinter = Some(hinter);
self
}

/// Set the [KonaHandleRegister] for execution.
pub fn with_handle_register(mut self, handler_register: KonaHandleRegister<F, H>) -> Self {
self.handler_register = Some(handler_register);
self
}

/// Build the [StatelessL2BlockExecutor] from the builder configuration.
pub fn build(self) -> Result<StatelessL2BlockExecutor<'a, F, H>> {
let fetcher = self.fetcher.ok_or(anyhow::anyhow!("Fetcher not set"))?;
let hinter = self.hinter.ok_or(anyhow::anyhow!("Hinter not set"))?;
pub fn build(self) -> StatelessL2BlockExecutor<'a, F, H> {
let parent_header = self.parent_header.unwrap_or_else(|| {
let default_header = Header::default();
default_header.seal_slow()
});

let trie_db = TrieDB::new(parent_header.state_root, parent_header, fetcher, hinter);
Ok(StatelessL2BlockExecutor {
let trie_db =
TrieDB::new(parent_header.state_root, parent_header, self.provider, self.hinter);
StatelessL2BlockExecutor {
config: self.config,
trie_db,
handler_register: self.handler_register,
})
}
}
}
4 changes: 2 additions & 2 deletions crates/executor/src/canyon.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Contains logic specific to Canyon hardfork activation.

use crate::errors::ExecutorResult;
use alloy_primitives::{address, b256, hex, Address, Bytes, B256};
use anyhow::Result;
use kona_mpt::{TrieDB, TrieHinter, TrieProvider};
use op_alloy_genesis::RollupConfig;
use revm::{
Expand All @@ -26,7 +26,7 @@ pub(crate) fn ensure_create2_deployer_canyon<F, H>(
db: &mut State<&mut TrieDB<F, H>>,
config: &RollupConfig,
timestamp: u64,
) -> Result<()>
) -> ExecutorResult<()>
where
F: TrieProvider,
H: TrieHinter,
Expand Down
30 changes: 17 additions & 13 deletions crates/executor/src/eip4788.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
//! Contains the logic for executing the pre-block beacon root call.

use crate::errors::{ExecutorError, ExecutorResult};
use alloc::{boxed::Box, vec::Vec};
use alloy_eips::eip4788::BEACON_ROOTS_ADDRESS;
use alloy_primitives::{Address, Bytes, B256, U256};
use anyhow::{anyhow, Result};
use kona_mpt::{TrieDB, TrieHinter, TrieProvider};
use op_alloy_genesis::RollupConfig;
use op_alloy_rpc_types_engine::OptimismPayloadAttributes;
use revm::{
db::State,
primitives::{
BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv,
},
Database, DatabaseCommit, Evm,
DatabaseCommit, Evm,
};

/// Execute the EIP-4788 pre-block beacon root contract call.
pub(crate) fn pre_block_beacon_root_contract_call<DB: Database + DatabaseCommit>(
db: &mut DB,
pub(crate) fn pre_block_beacon_root_contract_call<F, H>(
db: &mut State<&mut TrieDB<F, H>>,
config: &RollupConfig,
block_number: u64,
initialized_cfg: &CfgEnvWithHandlerCfg,
initialized_block_env: &BlockEnv,
payload: &OptimismPayloadAttributes,
) -> Result<()>
) -> ExecutorResult<()>
where
DB::Error: core::fmt::Display,
F: TrieProvider,
H: TrieHinter,
{
// apply pre-block EIP-4788 contract call
let mut evm_pre_block = Evm::builder()
Expand All @@ -46,28 +49,29 @@ where
}

/// Apply the EIP-4788 pre-block beacon root contract call to a given EVM instance.
fn apply_beacon_root_contract_call<EXT, DB: Database + DatabaseCommit>(
fn apply_beacon_root_contract_call<F, H>(
config: &RollupConfig,
timestamp: u64,
block_number: u64,
parent_beacon_block_root: Option<B256>,
evm: &mut Evm<'_, EXT, DB>,
) -> Result<()>
evm: &mut Evm<'_, (), &mut State<&mut TrieDB<F, H>>>,
) -> ExecutorResult<()>
where
DB::Error: core::fmt::Display,
F: TrieProvider,
H: TrieHinter,
{
if !config.is_ecotone_active(timestamp) {
return Ok(());
}

let parent_beacon_block_root =
parent_beacon_block_root.ok_or(anyhow!("missing parent beacon block root"))?;
parent_beacon_block_root.ok_or(ExecutorError::MissingParentBeaconBlockRoot)?;

// if the block number is zero (genesis block) then the parent beacon block root must
// be 0x0 and no system transaction may occur as per EIP-4788
if block_number == 0 {
if parent_beacon_block_root != B256::ZERO {
anyhow::bail!("Cancun genesis block parent beacon block root must be 0x0");
return Err(ExecutorError::MissingParentBeaconBlockRoot);
}
return Ok(());
}
Expand All @@ -82,7 +86,7 @@ where
Ok(res) => res.state,
Err(e) => {
evm.context.evm.env = previous_env;
anyhow::bail!("Failed to execute pre block call: {}", e);
return Err(ExecutorError::ExecutionError(e));
}
};

Expand Down
39 changes: 39 additions & 0 deletions crates/executor/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//! Errors for the `kona-executor` crate.

use kona_mpt::TrieDBError;
use revm::primitives::EVMError;
use thiserror::Error;

/// The error type for the [StatelessL2BlockExecutor].
///
/// [StatelessL2BlockExecutor]: crate::StatelessL2BlockExecutor
#[derive(Error, Debug)]
pub enum ExecutorError {
/// Missing gas limit in the payload attributes.
#[error("Gas limit not provided in payload attributes")]
MissingGasLimit,
/// Missing parent beacon block root in the payload attributes.
#[error("Parent beacon block root not provided in payload attributes")]
MissingParentBeaconBlockRoot,
/// Block gas limit exceeded.
#[error("Block gas limit exceeded")]
BlockGasLimitExceeded,
/// Unsupported transaction type.
#[error("Unsupported transaction type: {0}")]
UnsupportedTransactionType(u8),
/// Trie DB error.
#[error("Trie error: {0}")]
TrieDBError(#[from] TrieDBError),
/// Execution error.
#[error("Execution error: {0}")]
ExecutionError(EVMError<TrieDBError>),
/// Signature error.
#[error("Signature error: {0}")]
SignatureError(alloy_primitives::SignatureError),
/// RLP error.
#[error("RLP error: {0}")]
RLPError(alloy_eips::eip2718::Eip2718Error),
}

/// A [Result] type for the [ExecutorError] enum.
pub type ExecutorResult<T> = Result<T, ExecutorError>;
Loading