From c38d4ea57177eb4392c81b28e7458e4d4f0d2373 Mon Sep 17 00:00:00 2001 From: clabby Date: Sun, 16 Jun 2024 18:20:37 -0400 Subject: [PATCH] chore(workspace): `kona-executor` (#259) * 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 --- Cargo.lock | 20 ++++++- README.md | 3 +- bin/programs/client/Cargo.toml | 6 +- bin/programs/client/src/{main.rs => kona.rs} | 45 +++++---------- bin/programs/client/src/l1/driver.rs | 9 ++- bin/programs/client/src/l2/mod.rs | 7 +-- .../l2/{executor/hinter.rs => trie_hinter.rs} | 0 crates/executor/Cargo.toml | 28 ++++++++++ crates/executor/README.md | 3 + .../executor/src}/canyon.rs | 0 .../executor/src}/eip4788.rs | 0 .../mod.rs => crates/executor/src/lib.rs | 55 +++++++++---------- .../executor => crates/executor/src}/util.rs | 0 .../testdata/block_120794432_exec/output.json | 0 .../testdata/block_121003241_exec/output.json | 0 .../testdata/block_121049889_exec/output.json | 0 .../testdata/block_121057303_exec/output.json | 0 .../testdata/block_121065789_exec/output.json | 0 .../testdata/block_121135704_exec/output.json | 0 19 files changed, 108 insertions(+), 68 deletions(-) rename bin/programs/client/src/{main.rs => kona.rs} (71%) rename bin/programs/client/src/l2/{executor/hinter.rs => trie_hinter.rs} (100%) create mode 100644 crates/executor/Cargo.toml create mode 100644 crates/executor/README.md rename {bin/programs/client/src/l2/executor => crates/executor/src}/canyon.rs (100%) rename {bin/programs/client/src/l2/executor => crates/executor/src}/eip4788.rs (100%) rename bin/programs/client/src/l2/executor/mod.rs => crates/executor/src/lib.rs (99%) rename {bin/programs/client/src/l2/executor => crates/executor/src}/util.rs (100%) rename {bin/programs/client => crates/executor}/testdata/block_120794432_exec/output.json (100%) rename {bin/programs/client => crates/executor}/testdata/block_121003241_exec/output.json (100%) rename {bin/programs/client => crates/executor}/testdata/block_121049889_exec/output.json (100%) rename {bin/programs/client => crates/executor}/testdata/block_121057303_exec/output.json (100%) rename {bin/programs/client => crates/executor}/testdata/block_121065789_exec/output.json (100%) rename {bin/programs/client => crates/executor}/testdata/block_121135704_exec/output.json (100%) diff --git a/Cargo.lock b/Cargo.lock index def2de507..0b00692fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1685,12 +1685,12 @@ dependencies = [ "kona-common", "kona-common-proc", "kona-derive", + "kona-executor", "kona-mpt", "kona-preimage", "kona-primitives", "lru", "op-alloy-consensus", - "revm", "serde", "serde_json", "spin 0.9.8", @@ -1756,6 +1756,24 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "kona-executor" +version = "0.0.1" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "anyhow", + "kona-derive", + "kona-mpt", + "op-alloy-consensus", + "revm", + "serde", + "serde_json", + "tracing", +] + [[package]] name = "kona-host" version = "0.1.0" diff --git a/README.md b/README.md index eb49aa247..9e5f1f956 100644 --- a/README.md +++ b/README.md @@ -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` diff --git a/bin/programs/client/Cargo.toml b/bin/programs/client/Cargo.toml index 2e5cc2bc1..6fea94b48 100644 --- a/bin/programs/client/Cargo.toml +++ b/bin/programs/client/Cargo.toml @@ -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 @@ -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 } @@ -38,3 +38,7 @@ serde_json = "1.0.117" [features] tracing-subscriber = ["dep:tracing-subscriber"] + +[[bin]] +name = "kona" +path = "src/kona.rs" diff --git a/bin/programs/client/src/main.rs b/bin/programs/client/src/kona.rs similarity index 71% rename from bin/programs/client/src/main.rs rename to bin/programs/client/src/kona.rs index 3ddd26994..07cd6e182 100644 --- a/bin/programs/client/src/main.rs +++ b/bin/programs/client/src/kona.rs @@ -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; @@ -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 { //////////////////////////////////////////////////////////////// @@ -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()?; //////////////////////////////////////////////////////////////// @@ -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)) -} diff --git a/bin/programs/client/src/l1/driver.rs b/bin/programs/client/src/l1/driver.rs index ea2878b64..8f5603531 100644 --- a/bin/programs/client/src/l1/driver.rs +++ b/bin/programs/client/src/l1/driver.rs @@ -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
{ &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
{ + self.l2_safe_head_header + } + /// Creates a new [DerivationDriver] with the given configuration, blob provider, and chain /// providers. /// diff --git a/bin/programs/client/src/l2/mod.rs b/bin/programs/client/src/l2/mod.rs index 3b945c441..31ceb9323 100644 --- a/bin/programs/client/src/l2/mod.rs +++ b/bin/programs/client/src/l2/mod.rs @@ -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; diff --git a/bin/programs/client/src/l2/executor/hinter.rs b/bin/programs/client/src/l2/trie_hinter.rs similarity index 100% rename from bin/programs/client/src/l2/executor/hinter.rs rename to bin/programs/client/src/l2/trie_hinter.rs diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml new file mode 100644 index 000000000..d17826002 --- /dev/null +++ b/crates/executor/Cargo.toml @@ -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" diff --git a/crates/executor/README.md b/crates/executor/README.md new file mode 100644 index 000000000..470d700e3 --- /dev/null +++ b/crates/executor/README.md @@ -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`. diff --git a/bin/programs/client/src/l2/executor/canyon.rs b/crates/executor/src/canyon.rs similarity index 100% rename from bin/programs/client/src/l2/executor/canyon.rs rename to crates/executor/src/canyon.rs diff --git a/bin/programs/client/src/l2/executor/eip4788.rs b/crates/executor/src/eip4788.rs similarity index 100% rename from bin/programs/client/src/l2/executor/eip4788.rs rename to crates/executor/src/eip4788.rs diff --git a/bin/programs/client/src/l2/executor/mod.rs b/crates/executor/src/lib.rs similarity index 99% rename from bin/programs/client/src/l2/executor/mod.rs rename to crates/executor/src/lib.rs index c5d252fcc..acb519ae2 100644 --- a/bin/programs/client/src/l2/executor/mod.rs +++ b/crates/executor/src/lib.rs @@ -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}; @@ -17,37 +22,32 @@ 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 +pub struct StatelessL2BlockExecutor<'a, F, H> where F: TrieDBFetcher, H: TrieDBHinter, { /// The [RollupConfig]. - config: Arc, + config: &'a RollupConfig, /// The inner state database component. state: State>, } -impl StatelessL2BlockExecutor +impl<'a, F, H> StatelessL2BlockExecutor<'a, F, H> where F: TrieDBFetcher, H: TrieDBHinter, @@ -55,7 +55,7 @@ where /// Constructs a new [StatelessL2BlockExecutor] with the given starting state root, parent hash, /// and [TrieDBFetcher]. pub fn new( - config: Arc, + config: &'a RollupConfig, parent_header: Sealed
, fetcher: F, hinter: H, @@ -66,7 +66,7 @@ where } } -impl StatelessL2BlockExecutor +impl<'a, F, H> StatelessL2BlockExecutor<'a, F, H> where F: TrieDBFetcher, H: TrieDBHinter, @@ -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, ); @@ -112,7 +112,7 @@ 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, @@ -120,7 +120,7 @@ where )?; // 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. @@ -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}", @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, diff --git a/bin/programs/client/src/l2/executor/util.rs b/crates/executor/src/util.rs similarity index 100% rename from bin/programs/client/src/l2/executor/util.rs rename to crates/executor/src/util.rs diff --git a/bin/programs/client/testdata/block_120794432_exec/output.json b/crates/executor/testdata/block_120794432_exec/output.json similarity index 100% rename from bin/programs/client/testdata/block_120794432_exec/output.json rename to crates/executor/testdata/block_120794432_exec/output.json diff --git a/bin/programs/client/testdata/block_121003241_exec/output.json b/crates/executor/testdata/block_121003241_exec/output.json similarity index 100% rename from bin/programs/client/testdata/block_121003241_exec/output.json rename to crates/executor/testdata/block_121003241_exec/output.json diff --git a/bin/programs/client/testdata/block_121049889_exec/output.json b/crates/executor/testdata/block_121049889_exec/output.json similarity index 100% rename from bin/programs/client/testdata/block_121049889_exec/output.json rename to crates/executor/testdata/block_121049889_exec/output.json diff --git a/bin/programs/client/testdata/block_121057303_exec/output.json b/crates/executor/testdata/block_121057303_exec/output.json similarity index 100% rename from bin/programs/client/testdata/block_121057303_exec/output.json rename to crates/executor/testdata/block_121057303_exec/output.json diff --git a/bin/programs/client/testdata/block_121065789_exec/output.json b/crates/executor/testdata/block_121065789_exec/output.json similarity index 100% rename from bin/programs/client/testdata/block_121065789_exec/output.json rename to crates/executor/testdata/block_121065789_exec/output.json diff --git a/bin/programs/client/testdata/block_121135704_exec/output.json b/crates/executor/testdata/block_121135704_exec/output.json similarity index 100% rename from bin/programs/client/testdata/block_121135704_exec/output.json rename to crates/executor/testdata/block_121135704_exec/output.json