diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml index eaadf5be1b..8225df919b 100644 --- a/crates/executor/Cargo.toml +++ b/crates/executor/Cargo.toml @@ -11,6 +11,9 @@ homepage.workspace = true [lints] workspace = true +[profile.bench] +default = ["kona-mpt/test-utils"] + [dependencies] # General thiserror.workspace = true diff --git a/crates/executor/benches/execution.rs b/crates/executor/benches/execution.rs index b3895ef55a..1c836f3b60 100644 --- a/crates/executor/benches/execution.rs +++ b/crates/executor/benches/execution.rs @@ -8,7 +8,7 @@ use alloy_rpc_types_engine::PayloadAttributes; use anyhow::{anyhow, Result}; use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use kona_executor::StatelessL2BlockExecutor; -use kona_mpt::{NoopTrieHinter, TrieProvider}; +use kona_mpt::{test_utils::NoopTrieHinter, TrieProvider}; use op_alloy_genesis::{RollupConfig, OP_MAINNET_BASE_FEE_PARAMS}; use op_alloy_rpc_types_engine::OptimismPayloadAttributes; use pprof::criterion::{Output, PProfProfiler}; diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index 807c81c2f1..6cf1abad3e 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -703,7 +703,7 @@ mod test { use alloy_rlp::Decodable; use alloy_rpc_types_engine::PayloadAttributes; use anyhow::{anyhow, Result}; - use kona_mpt::NoopTrieHinter; + use kona_mpt::test_utils::NoopTrieHinter; use op_alloy_genesis::OP_MAINNET_BASE_FEE_PARAMS; use serde::Deserialize; use std::collections::HashMap; diff --git a/crates/mpt/Cargo.toml b/crates/mpt/Cargo.toml index ba11ca7307..ccca7b5669 100644 --- a/crates/mpt/Cargo.toml +++ b/crates/mpt/Cargo.toml @@ -11,11 +11,20 @@ homepage.workspace = true [lints] workspace = true +[profile.bench] +default = ["test-utils"] + [dependencies] # General tracing.workspace = true thiserror.workspace = true +# `test-utils` +anyhow = { workspace = true, optional = true } +reqwest = { workspace = true, optional = true } +alloy-provider = { workspace = true, features = ["reqwest"], optional = true } +alloy-rpc-types = { workspace = true, features = ["eth"], optional = true } + # Revm + Alloy revm.workspace = true alloy-primitives = { workspace = true, features = ["rlp"] } @@ -25,7 +34,6 @@ alloy-trie.workspace = true [dev-dependencies] tokio.workspace = true -anyhow.workspace = true reqwest.workspace = true futures.workspace = true tracing-subscriber.workspace = true @@ -40,6 +48,15 @@ proptest.workspace = true criterion.workspace = true pprof.workspace = true +[features] +default = [] +test-utils = [ + "dep:anyhow", + "dep:reqwest", + "dep:alloy-provider", + "dep:alloy-rpc-types", +] + [[bench]] name = "trie_node" harness = false diff --git a/crates/mpt/benches/trie_node.rs b/crates/mpt/benches/trie_node.rs index d8eaa3fded..5e56a919da 100644 --- a/crates/mpt/benches/trie_node.rs +++ b/crates/mpt/benches/trie_node.rs @@ -3,7 +3,10 @@ use alloy_trie::Nibbles; use criterion::{criterion_group, criterion_main, Criterion}; -use kona_mpt::{NoopTrieHinter, NoopTrieProvider, TrieNode}; +use kona_mpt::{ + test_utils::{NoopTrieHinter, NoopTrieProvider}, + TrieNode, +}; use pprof::criterion::{Output, PProfProfiler}; use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng}; diff --git a/crates/mpt/src/db/mod.rs b/crates/mpt/src/db/mod.rs index 12da988b8e..3a3beb8233 100644 --- a/crates/mpt/src/db/mod.rs +++ b/crates/mpt/src/db/mod.rs @@ -46,34 +46,37 @@ pub use account::TrieAccount; /// [BLOCK_HASH_HISTORY] blocks back relative to the current parent block hash. /// /// **Example Construction**: -/// ```rust -/// use alloy_consensus::{Header, Sealable}; -/// use alloy_primitives::{Bytes, B256}; -/// use anyhow::Result; -/// use kona_mpt::{NoopTrieHinter, NoopTrieProvider, TrieDB}; -/// use revm::{db::states::bundle_state::BundleRetention, EvmBuilder, StateBuilder}; -/// -/// let mock_starting_root = B256::default(); -/// let mock_parent_block_header = Header::default(); -/// -/// let trie_db = TrieDB::new( -/// mock_starting_root, -/// mock_parent_block_header.seal_slow(), -/// NoopTrieProvider, -/// NoopTrieHinter, -/// ); -/// let mut state = StateBuilder::new_with_database(trie_db).with_bundle_update().build(); -/// let evm = EvmBuilder::default().with_db(&mut state).build(); -/// -/// // Execute your block's transactions... -/// -/// // Drop the EVM prior to merging the state transitions. -/// drop(evm); -/// -/// state.merge_transitions(BundleRetention::Reverts); -/// let bundle = state.take_bundle(); -/// let state_root = state.database.state_root(&bundle).expect("Failed to compute state root"); -/// ``` +#[cfg_attr( + feature = "test-utils", + doc = " +use alloy_consensus::{Header, Sealable}; +use alloy_primitives::{Bytes, B256}; +use anyhow::Result; +use kona_mpt::{NoopTrieHinter, NoopTrieProvider, TrieDB}; +use revm::{db::states::bundle_state::BundleRetention, EvmBuilder, StateBuilder}; + +let mock_starting_root = B256::default(); +let mock_parent_block_header = Header::default(); + +let trie_db = TrieDB::new( + mock_starting_root, + mock_parent_block_header.seal_slow(), + NoopTrieProvider, + NoopTrieHinter, +); +let mut state = StateBuilder::new_with_database(trie_db).with_bundle_update().build(); +let evm = EvmBuilder::default().with_db(&mut state).build(); + +// Execute your block's transactions... + +// Drop the EVM prior to merging the state transitions. +drop(evm); + +state.merge_transitions(BundleRetention::Reverts); +let bundle = state.take_bundle(); +let state_root = state.database.state_root(&bundle).expect(\"Failed to compute state root\"); +" +)] /// /// [State]: revm::State #[derive(Debug, Clone)] diff --git a/crates/mpt/src/fetcher.rs b/crates/mpt/src/fetcher.rs index 280ac878da..16e7f506d0 100644 --- a/crates/mpt/src/fetcher.rs +++ b/crates/mpt/src/fetcher.rs @@ -1,7 +1,7 @@ //! Contains the [TrieProvider] trait for fetching trie node preimages, contract bytecode, and //! headers. -use alloc::string::{String, ToString}; +use alloc::string::ToString; use alloy_consensus::Header; use alloy_primitives::{Address, Bytes, B256, U256}; use core::fmt::Display; @@ -93,48 +93,3 @@ pub trait TrieHinter { block_number: u64, ) -> Result<(), Self::Error>; } - -/// The default, no-op implementation of the [TrieProvider] trait, used for testing. -#[derive(Debug, Clone, Copy)] -pub struct NoopTrieProvider; - -impl TrieProvider for NoopTrieProvider { - type Error = String; - - fn trie_node_preimage(&self, _key: B256) -> Result { - Ok(Bytes::new()) - } - - fn bytecode_by_hash(&self, _code_hash: B256) -> Result { - Ok(Bytes::new()) - } - - fn header_by_hash(&self, _hash: B256) -> Result { - Ok(Header::default()) - } -} - -/// The default, no-op implementation of the [TrieHinter] trait, used for testing. -#[derive(Debug, Clone, Copy)] -pub struct NoopTrieHinter; - -impl TrieHinter for NoopTrieHinter { - type Error = String; - - fn hint_trie_node(&self, _hash: B256) -> Result<(), Self::Error> { - Ok(()) - } - - fn hint_account_proof(&self, _address: Address, _block_number: u64) -> Result<(), Self::Error> { - Ok(()) - } - - fn hint_storage_proof( - &self, - _address: Address, - _slot: U256, - _block_number: u64, - ) -> Result<(), Self::Error> { - Ok(()) - } -} diff --git a/crates/mpt/src/lib.rs b/crates/mpt/src/lib.rs index 8db704da0f..10f489e5b7 100644 --- a/crates/mpt/src/lib.rs +++ b/crates/mpt/src/lib.rs @@ -19,7 +19,7 @@ pub use errors::{ }; mod fetcher; -pub use fetcher::{NoopTrieHinter, NoopTrieProvider, TrieHinter, TrieProvider}; +pub use fetcher::{TrieHinter, TrieProvider}; mod node; pub use node::TrieNode; @@ -30,5 +30,5 @@ pub use list_walker::OrderedListWalker; mod util; pub use util::ordered_trie_with_encoder; -#[cfg(test)] -mod test_util; +#[cfg(any(test, feature = "test-utils"))] +pub mod test_utils; diff --git a/crates/mpt/src/list_walker.rs b/crates/mpt/src/list_walker.rs index 3ec3596510..04a3dba0ca 100644 --- a/crates/mpt/src/list_walker.rs +++ b/crates/mpt/src/list_walker.rs @@ -166,11 +166,10 @@ mod test { use super::*; use crate::{ ordered_trie_with_encoder, - test_util::{ + test_utils::{ get_live_derivable_receipts_list, get_live_derivable_transactions_list, - TrieNodeProvider, + NoopTrieProvider, TrieNodeProvider, }, - NoopTrieProvider, }; use alloc::{collections::BTreeMap, string::String, vec::Vec}; use alloy_consensus::{ReceiptEnvelope, TxEnvelope}; diff --git a/crates/mpt/src/node.rs b/crates/mpt/src/node.rs index d7976896aa..1c6405664e 100644 --- a/crates/mpt/src/node.rs +++ b/crates/mpt/src/node.rs @@ -684,8 +684,9 @@ impl Decodable for TrieNode { mod test { use super::*; use crate::{ - fetcher::NoopTrieProvider, ordered_trie_with_encoder, test_util::TrieNodeProvider, - NoopTrieHinter, TrieNode, + ordered_trie_with_encoder, + test_utils::{NoopTrieHinter, NoopTrieProvider, TrieNodeProvider}, + TrieNode, }; use alloc::{collections::BTreeMap, vec, vec::Vec}; use alloy_primitives::{b256, bytes, hex, keccak256}; diff --git a/crates/mpt/src/test_util.rs b/crates/mpt/src/test_utils.rs similarity index 75% rename from crates/mpt/src/test_util.rs rename to crates/mpt/src/test_utils.rs index d4bba38db7..5dede147b7 100644 --- a/crates/mpt/src/test_util.rs +++ b/crates/mpt/src/test_utils.rs @@ -1,9 +1,9 @@ //! Testing utilities for `kona-mpt` -use crate::{ordered_trie_with_encoder, TrieProvider}; -use alloc::{collections::BTreeMap, vec::Vec}; -use alloy_consensus::{Receipt, ReceiptEnvelope, ReceiptWithBloom, TxEnvelope, TxType}; -use alloy_primitives::{keccak256, Bytes, Log, B256}; +use crate::{ordered_trie_with_encoder, TrieHinter, TrieProvider}; +use alloc::{collections::BTreeMap, string::String, vec::Vec}; +use alloy_consensus::{Header, Receipt, ReceiptEnvelope, ReceiptWithBloom, TxEnvelope, TxType}; +use alloy_primitives::{keccak256, Address, Bytes, Log, B256, U256}; use alloy_provider::{network::eip2718::Encodable2718, Provider, ProviderBuilder}; use alloy_rpc_types::{BlockTransactions, BlockTransactionsKind}; use anyhow::{anyhow, Result}; @@ -12,7 +12,7 @@ use reqwest::Url; const RPC_URL: &str = "https://docs-demo.quiknode.pro/"; /// Grabs a live merkleized receipts list within a block header. -pub(crate) async fn get_live_derivable_receipts_list( +pub async fn get_live_derivable_receipts_list( ) -> Result<(B256, BTreeMap, Vec)> { // Initialize the provider. let provider = ProviderBuilder::new().on_http(Url::parse(RPC_URL).expect("invalid rpc url")); @@ -78,7 +78,7 @@ pub(crate) async fn get_live_derivable_receipts_list( } /// Grabs a live merkleized transactions list within a block header. -pub(crate) async fn get_live_derivable_transactions_list( +pub async fn get_live_derivable_transactions_list( ) -> Result<(B256, BTreeMap, Vec)> { // Initialize the provider. let provider = ProviderBuilder::new().on_http(Url::parse(RPC_URL).expect("invalid rpc url")); @@ -118,15 +118,62 @@ pub(crate) async fn get_live_derivable_transactions_list( Ok((root, preimages, consensus_txs)) } +/// The default, no-op implementation of the [TrieProvider] trait, used for testing. +#[derive(Debug, Clone, Copy)] +pub struct NoopTrieProvider; + +impl TrieProvider for NoopTrieProvider { + type Error = String; + + fn trie_node_preimage(&self, _key: B256) -> Result { + Ok(Bytes::new()) + } + + fn bytecode_by_hash(&self, _code_hash: B256) -> Result { + Ok(Bytes::new()) + } + + fn header_by_hash(&self, _hash: B256) -> Result { + Ok(Header::default()) + } +} + +/// The default, no-op implementation of the [TrieHinter] trait, used for testing. +#[derive(Debug, Clone, Copy)] +pub struct NoopTrieHinter; + +impl TrieHinter for NoopTrieHinter { + type Error = String; + + fn hint_trie_node(&self, _hash: B256) -> Result<(), Self::Error> { + Ok(()) + } + + fn hint_account_proof(&self, _address: Address, _block_number: u64) -> Result<(), Self::Error> { + Ok(()) + } + + fn hint_storage_proof( + &self, + _address: Address, + _slot: U256, + _block_number: u64, + ) -> Result<(), Self::Error> { + Ok(()) + } +} + /// A mock [TrieProvider] for testing that serves in-memory preimages. -pub(crate) struct TrieNodeProvider { +#[derive(Debug, Clone)] +pub struct TrieNodeProvider { preimages: BTreeMap, bytecode: BTreeMap, headers: BTreeMap, } impl TrieNodeProvider { - pub(crate) const fn new( + /// Constructs a new [TrieNodeProvider]. + pub const fn new( preimages: BTreeMap, bytecode: BTreeMap, headers: BTreeMap,