Skip to content

Commit

Permalink
chore(workspace): kona-executor (#259)
Browse files Browse the repository at this point in the history
* chore(workspace): `kona-executor`

Splits out the executor in the client program into its own crate, so
that it may be used downstream by other backends more easily. It is not
coupled to any of the `kona-preimage` platforms, so teams like succinct
can implement their own backends for the trie traits.

* andreas review
  • Loading branch information
clabby authored Jun 16, 2024
1 parent 49a9d9c commit c38d4ea
Show file tree
Hide file tree
Showing 19 changed files with 108 additions and 68 deletions.
20 changes: 19 additions & 1 deletion Cargo.lock

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

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ verify an [L2 output root][g-output-root] from the L1 inputs it was [derived fro
- [`common-proc`](./crates/common-proc): Proc macro for the `client` program entrypoint.
- [`primitives`](./crates/primitives): Primitive types for use in `kona` crates.
- [`preimage`](./crates/preimage): High level interfaces to the [`PreimageOracle`][fpp-specs] ABI
- [`mpt`](./crrates/mpt): Utilities for interacting with the Merkle Patricia Trie in the client program.
- [`mpt`](./crates/mpt): Utilities for interacting with the Merkle Patricia Trie in the client program.
- [`executor`](./crates/executor): `no_std` stateless block executor for the [OP Stack][op-stack].
- [`derive`](./crates/derive): `no_std` compatible implementation of the [derivation pipeline][g-derivation-pipeline].
- [`plasma`](./crates/plasma/): Plasma extension to `kona-derive`

Expand Down
6 changes: 5 additions & 1 deletion bin/programs/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ alloy-rlp.workspace = true
alloy-eips.workspace = true
op-alloy-consensus.workspace = true
anyhow.workspace = true
revm = { workspace = true, features = ["optimism"] }
lru.workspace = true
spin.workspace = true
async-trait.workspace = true
Expand All @@ -29,6 +28,7 @@ kona-preimage = { path = "../../../crates/preimage", version = "0.0.1" }
kona-primitives = { path = "../../../crates/primitives", version = "0.0.1" }
kona-mpt = { path = "../../../crates/mpt", version = "0.0.1" }
kona-derive = { path = "../../../crates/derive", default-features = false, version = "0.0.1" }
kona-executor = { path = "../../../crates/executor", version = "0.0.1" }

tracing-subscriber = { version = "0.3.18", optional = true }

Expand All @@ -38,3 +38,7 @@ serde_json = "1.0.117"

[features]
tracing-subscriber = ["dep:tracing-subscriber"]

[[bin]]
name = "kona"
path = "src/kona.rs"
45 changes: 14 additions & 31 deletions bin/programs/client/src/main.rs → bin/programs/client/src/kona.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ use alloc::sync::Arc;
use alloy_consensus::Header;
use kona_client::{
l1::{DerivationDriver, OracleBlobProvider, OracleL1ChainProvider},
l2::{OracleL2ChainProvider, StatelessL2BlockExecutor, TrieDBHintWriter},
l2::{OracleL2ChainProvider, TrieDBHintWriter},
BootInfo, CachingOracle,
};
use kona_common_proc::client_entry;
use kona_executor::StatelessL2BlockExecutor;
use kona_primitives::L2AttributesWithParent;

extern crate alloc;

Expand All @@ -22,7 +24,13 @@ const ORACLE_LRU_SIZE: usize = 1024;
#[client_entry(0x77359400)]
fn main() -> Result<()> {
#[cfg(feature = "tracing-subscriber")]
init_tracing_subscriber(3)?;
{
use anyhow::anyhow;
use tracing::Level;

let subscriber = tracing_subscriber::fmt().with_max_level(Level::DEBUG).finish();
tracing::subscriber::set_global_default(subscriber).map_err(|e| anyhow!(e))?;
}

kona_common::block_on(async move {
////////////////////////////////////////////////////////////////
Expand All @@ -47,16 +55,15 @@ fn main() -> Result<()> {
l2_provider.clone(),
)
.await?;
let attributes = driver.produce_disputed_payload().await?;
let L2AttributesWithParent { attributes, .. } = driver.produce_disputed_payload().await?;

let cfg = Arc::new(boot.rollup_config.clone());
let mut executor = StatelessL2BlockExecutor::new(
cfg,
driver.l2_safe_head_header().clone(),
&boot.rollup_config,
driver.take_l2_safe_head_header(),
l2_provider,
TrieDBHintWriter,
);
let Header { number, .. } = *executor.execute_payload(attributes.attributes)?;
let Header { number, .. } = *executor.execute_payload(attributes)?;
let output_root = executor.compute_output_root()?;

////////////////////////////////////////////////////////////////
Expand All @@ -76,27 +83,3 @@ fn main() -> Result<()> {
Ok::<_, anyhow::Error>(())
})
}

/// Initializes the tracing subscriber
///
/// # Arguments
/// * `verbosity_level` - The verbosity level (0-4)
///
/// # Returns
/// * `Result<()>` - Ok if successful, Err otherwise.
#[cfg(feature = "tracing-subscriber")]
pub fn init_tracing_subscriber(verbosity_level: u8) -> anyhow::Result<()> {
use anyhow::anyhow;
use tracing::Level;

let subscriber = tracing_subscriber::fmt()
.with_max_level(match verbosity_level {
0 => Level::ERROR,
1 => Level::WARN,
2 => Level::INFO,
3 => Level::DEBUG,
_ => Level::TRACE,
})
.finish();
tracing::subscriber::set_global_default(subscriber).map_err(|e| anyhow!(e))
}
9 changes: 7 additions & 2 deletions bin/programs/client/src/l1/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,21 @@ pub struct DerivationDriver {
}

impl DerivationDriver {
/// Returns the current L2 safe head block information.
/// Returns the current L2 safe head [L2BlockInfo].
pub fn l2_safe_head(&self) -> &L2BlockInfo {
&self.l2_safe_head
}

/// Returns the header of the current L2 safe head.
/// Returns the [Header] of the current L2 safe head.
pub fn l2_safe_head_header(&self) -> &Sealed<Header> {
&self.l2_safe_head_header
}

/// Consumes self and returns the owned [Header] of the current L2 safe head.
pub fn take_l2_safe_head_header(self) -> Sealed<Header> {
self.l2_safe_head_header
}

/// Creates a new [DerivationDriver] with the given configuration, blob provider, and chain
/// providers.
///
Expand Down
7 changes: 3 additions & 4 deletions bin/programs/client/src/l2/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Contains the L2-specifc contstructs of the client program, such as the
//! [StatelessL2BlockExecutor]
//! Contains the L2-specifc contstructs of the client program.
mod executor;
pub use executor::{StatelessL2BlockExecutor, TrieDBHintWriter};
mod trie_hinter;
pub use trie_hinter::TrieDBHintWriter;

mod chain_provider;
pub use chain_provider::OracleL2ChainProvider;
File renamed without changes.
28 changes: 28 additions & 0 deletions crates/executor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "kona-executor"
description = "An no_std implementation of a stateless L2 block executor for the OP Stack."
version = "0.0.1"
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true

[dependencies]
# workspace
anyhow.workspace = true
tracing.workspace = true
alloy-primitives = { workspace = true, features = ["rlp"] }
alloy-rlp.workspace = true
alloy-eips.workspace = true
alloy-consensus.workspace = true
op-alloy-consensus.workspace = true
revm = { workspace = true, features = ["optimism"] }

# local
kona-mpt = { path = "../mpt", version = "0.0.1" }
kona-derive = { path = "../derive", version = "0.0.1" }

[dev-dependencies]
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.117"
3 changes: 3 additions & 0 deletions crates/executor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `kona-executor`

A `no_std` implementation of a stateless block executor for the OP stack, backed by [`kona-mpt`](../mpt)'s `TrieDB`.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
//! The block executor for the L2 client program. Operates off of a [TrieDB] backed [State],
//! allowing for stateless block execution of OP Stack blocks.
#![doc = include_str!("../README.md")]
#![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)]
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![no_std]

use alloc::{sync::Arc, vec::Vec};
extern crate alloc;

use alloc::vec::Vec;
use alloy_consensus::{Header, Sealable, Sealed, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH};
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
use alloy_primitives::{address, keccak256, Address, Bytes, TxKind, B256, U256};
Expand All @@ -17,45 +22,40 @@ use revm::{
},
Evm, StateBuilder,
};

mod hinter;
pub use hinter::TrieDBHintWriter;
use tracing::{debug, info};

mod eip4788;
pub(crate) use eip4788::pre_block_beacon_root_contract_call;
use eip4788::pre_block_beacon_root_contract_call;

mod canyon;
pub(crate) use canyon::ensure_create2_deployer_canyon;
use canyon::ensure_create2_deployer_canyon;

mod util;
use tracing::{debug, info};
pub(crate) use util::{logs_bloom, wrap_receipt_with_bloom};

use self::util::{extract_tx_gas_limit, is_system_transaction};
use util::{extract_tx_gas_limit, is_system_transaction, logs_bloom, wrap_receipt_with_bloom};

/// The block executor for the L2 client program. Operates off of a [TrieDB] backed [State],
/// allowing for stateless block execution of OP Stack blocks.
#[derive(Debug)]
pub struct StatelessL2BlockExecutor<F, H>
pub struct StatelessL2BlockExecutor<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
{
/// The [RollupConfig].
config: Arc<RollupConfig>,
config: &'a RollupConfig,
/// The inner state database component.
state: State<TrieDB<F, H>>,
}

impl<F, H> StatelessL2BlockExecutor<F, H>
impl<'a, F, H> StatelessL2BlockExecutor<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
{
/// Constructs a new [StatelessL2BlockExecutor] with the given starting state root, parent hash,
/// and [TrieDBFetcher].
pub fn new(
config: Arc<RollupConfig>,
config: &'a RollupConfig,
parent_header: Sealed<Header>,
fetcher: F,
hinter: H,
Expand All @@ -66,7 +66,7 @@ where
}
}

impl<F, H> StatelessL2BlockExecutor<F, H>
impl<'a, F, H> StatelessL2BlockExecutor<'a, F, H>
where
F: TrieDBFetcher,
H: TrieDBHinter,
Expand All @@ -91,7 +91,7 @@ where
// Prepare the `revm` environment.
let initialized_block_env = Self::prepare_block_env(
self.revm_spec_id(payload.timestamp),
self.config.as_ref(),
self.config,
self.state.database.parent_block_header(),
&payload,
);
Expand All @@ -112,15 +112,15 @@ where
// Apply the pre-block EIP-4788 contract call.
pre_block_beacon_root_contract_call(
&mut self.state,
self.config.as_ref(),
self.config,
block_number,
&initialized_cfg,
&initialized_block_env,
&payload,
)?;

// Ensure that the create2 contract is deployed upon transition to the Canyon hardfork.
ensure_create2_deployer_canyon(&mut self.state, self.config.as_ref(), payload.timestamp)?;
ensure_create2_deployer_canyon(&mut self.state, self.config, payload.timestamp)?;

// Construct the EVM with the given configuration.
// TODO(clabby): Accelerate precompiles w/ custom precompile handler.
Expand Down Expand Up @@ -237,8 +237,7 @@ where
let state_root = self.state.database.state_root(&bundle)?;

let transactions_root = Self::compute_transactions_root(payload.transactions.as_slice());
let receipts_root =
Self::compute_receipts_root(&receipts, self.config.as_ref(), payload.timestamp);
let receipts_root = Self::compute_receipts_root(&receipts, self.config, payload.timestamp);
debug!(
target: "client_executor",
"Computed transactions root: {transactions_root} | receipts root: {receipts_root}",
Expand Down Expand Up @@ -717,7 +716,7 @@ mod test {

// Initialize the block executor on block #120794431's post-state.
let mut l2_block_executor = StatelessL2BlockExecutor::new(
Arc::new(rollup_config),
&rollup_config,
header.seal_slow(),
TestdataTrieDBFetcher::new("block_120794432_exec"),
NoopTrieDBHinter,
Expand Down Expand Up @@ -770,7 +769,7 @@ mod test {

// Initialize the block executor on block #121049888's post-state.
let mut l2_block_executor = StatelessL2BlockExecutor::new(
Arc::new(rollup_config),
&rollup_config,
parent_header.seal_slow(),
TestdataTrieDBFetcher::new("block_121049889_exec"),
NoopTrieDBHinter,
Expand Down Expand Up @@ -827,7 +826,7 @@ mod test {

// Initialize the block executor on block #121003240's post-state.
let mut l2_block_executor = StatelessL2BlockExecutor::new(
Arc::new(rollup_config),
&rollup_config,
parent_header.seal_slow(),
TestdataTrieDBFetcher::new("block_121003241_exec"),
NoopTrieDBHinter,
Expand Down Expand Up @@ -891,7 +890,7 @@ mod test {

// Initialize the block executor on block #121057302's post-state.
let mut l2_block_executor = StatelessL2BlockExecutor::new(
Arc::new(rollup_config),
&rollup_config,
parent_header.seal_slow(),
TestdataTrieDBFetcher::new("block_121057303_exec"),
NoopTrieDBHinter,
Expand Down Expand Up @@ -949,7 +948,7 @@ mod test {

// Initialize the block executor on block #121057302's post-state.
let mut l2_block_executor = StatelessL2BlockExecutor::new(
Arc::new(rollup_config),
&rollup_config,
parent_header.seal_slow(),
TestdataTrieDBFetcher::new("block_121065789_exec"),
NoopTrieDBHinter,
Expand Down Expand Up @@ -1016,7 +1015,7 @@ mod test {

// Initialize the block executor on block #121135703's post-state.
let mut l2_block_executor = StatelessL2BlockExecutor::new(
Arc::new(rollup_config),
&rollup_config,
parent_header.seal_slow(),
TestdataTrieDBFetcher::new("block_121135704_exec"),
NoopTrieDBHinter,
Expand Down
File renamed without changes.

0 comments on commit c38d4ea

Please sign in to comment.