diff --git a/bin/host/src/fetcher/mod.rs b/bin/host/src/fetcher/mod.rs index aabcf9e97..06bbc3e59 100644 --- a/bin/host/src/fetcher/mod.rs +++ b/bin/host/src/fetcher/mod.rs @@ -9,14 +9,12 @@ use alloy_provider::{Provider, ReqwestProvider}; use alloy_rlp::Decodable; use alloy_rpc_types::{Block, BlockTransactions}; use anyhow::{anyhow, Result}; +use kona_client::HintType; use kona_preimage::{PreimageKey, PreimageKeyType}; use std::sync::Arc; use tokio::sync::RwLock; use tracing::debug; -mod hint; -pub use hint::HintType; - mod precompiles; /// The [Fetcher] struct is responsible for fetching preimages from a remote source. @@ -191,7 +189,7 @@ where anyhow::bail!("Invalid hint data length: {}", hint_data.len()); } - // Fetch the raw header from the L1 chain provider. + // Fetch the raw header from the L2 chain provider. let hash: B256 = hint_data .as_ref() .try_into() @@ -210,7 +208,43 @@ where raw_header.into(), ); } - HintType::L2Transactions => todo!(), + HintType::L2Transactions => { + // Validate the hint data length. + if hint_data.len() != 32 { + anyhow::bail!("Invalid hint data length: {}", hint_data.len()); + } + + // Fetch the block from the L2 chain provider and store the transactions within its + // body in the key-value store. + let hash: B256 = hint_data + .as_ref() + .try_into() + .map_err(|e| anyhow!("Failed to convert bytes to B256: {e}"))?; + let Block { transactions, .. } = self + .l2_provider + .get_block_by_hash(hash, false) + .await + .map_err(|e| anyhow!("Failed to fetch block: {e}"))? + .ok_or(anyhow!("Block not found."))?; + + match transactions { + BlockTransactions::Hashes(transactions) => { + let mut encoded_transactions = Vec::with_capacity(transactions.len()); + for tx_hash in transactions { + let tx = self + .l2_provider + .client() + .request::<&[B256; 1], Bytes>("debug_getRawTransaction", &[tx_hash]) + .await + .map_err(|e| anyhow!("Error fetching transaction: {e}"))?; + encoded_transactions.push(tx); + } + + self.store_trie_nodes(encoded_transactions.as_slice()).await?; + } + _ => anyhow::bail!("Only BlockTransactions::Hashes are supported."), + }; + } HintType::L2Code => { // geth hashdb scheme code hash key prefix const CODE_PREFIX: u8 = b'c'; @@ -277,11 +311,11 @@ where .await .map_err(|e| anyhow!("Failed to fetch account proof: {e}"))?; - let mut raw_output = [0u8; 97]; - raw_output[0] = OUTPUT_ROOT_VERSION; - raw_output[1..33].copy_from_slice(header.state_root.as_ref()); - raw_output[33..65].copy_from_slice(l2_to_l1_message_passer.storage_hash.as_ref()); - raw_output[65..97].copy_from_slice(self.l2_head.as_ref()); + let mut raw_output = [0u8; 128]; + raw_output[31] = OUTPUT_ROOT_VERSION; + raw_output[32..64].copy_from_slice(header.state_root.as_ref()); + raw_output[64..96].copy_from_slice(l2_to_l1_message_passer.storage_hash.as_ref()); + raw_output[96..128].copy_from_slice(self.l2_head.as_ref()); let output_root = keccak256(raw_output); let mut kv_write_lock = self.kv_store.write().await; @@ -405,9 +439,11 @@ where let mut hb = kona_mpt::ordered_trie_with_encoder(nodes, |node, buf| { buf.put_slice(node.as_ref()); }); + hb.root(); let intermediates = hb.take_proofs(); let mut kv_write_lock = self.kv_store.write().await; + for (_, value) in intermediates.into_iter() { let value_hash = keccak256(value.as_ref()); let key = PreimageKey::new(*value_hash, PreimageKeyType::Keccak256); diff --git a/bin/host/src/util.rs b/bin/host/src/util.rs index d14a00b6a..f08444e04 100644 --- a/bin/host/src/util.rs +++ b/bin/host/src/util.rs @@ -1,11 +1,12 @@ //! Contains utility functions and helpers for the host program. -use crate::{fetcher::HintType, types::NativePipeFiles}; +use crate::types::NativePipeFiles; use alloy_primitives::{hex, Bytes}; use alloy_provider::ReqwestProvider; use alloy_rpc_client::RpcClient; use alloy_transport_http::Http; use anyhow::{anyhow, Result}; +use kona_client::HintType; use kona_common::FileDescriptor; use kona_preimage::PipeHandle; use reqwest::Client; diff --git a/bin/programs/client/src/comms/caching_oracle.rs b/bin/programs/client/src/comms/caching_oracle.rs index 8099eeb8e..ab3d84df2 100644 --- a/bin/programs/client/src/comms/caching_oracle.rs +++ b/bin/programs/client/src/comms/caching_oracle.rs @@ -17,33 +17,27 @@ use spin::Mutex; /// /// [OracleReader]: kona_preimage::OracleReader #[derive(Debug, Clone)] -pub struct CachingOracle { +pub struct CachingOracle { /// The spin-locked cache that stores the responses from the oracle. cache: Arc>>>, } -impl CachingOracle { +impl CachingOracle { /// Creates a new [CachingOracle] that wraps the given [OracleReader] and stores up to `N` /// responses in the cache. /// /// [OracleReader]: kona_preimage::OracleReader - pub fn new() -> Self { + pub fn new(cache_size: usize) -> Self { Self { cache: Arc::new(Mutex::new(LruCache::new( - NonZeroUsize::new(N).expect("N must be greater than 0"), + NonZeroUsize::new(cache_size).expect("N must be greater than 0"), ))), } } } -impl Default for CachingOracle { - fn default() -> Self { - Self::new() - } -} - #[async_trait] -impl PreimageOracleClient for CachingOracle { +impl PreimageOracleClient for CachingOracle { async fn get(&self, key: PreimageKey) -> Result> { let mut cache_lock = self.cache.lock(); if let Some(value) = cache_lock.get(&key) { diff --git a/bin/host/src/fetcher/hint.rs b/bin/programs/client/src/hint.rs similarity index 87% rename from bin/host/src/fetcher/hint.rs rename to bin/programs/client/src/hint.rs index 2d1398e3a..ceea76631 100644 --- a/bin/host/src/fetcher/hint.rs +++ b/bin/programs/client/src/hint.rs @@ -1,6 +1,9 @@ //! This module contains the [HintType] enum. -use std::fmt::Display; +use core::fmt::Display; + +use alloc::{string::String, vec::Vec}; +use alloy_primitives::hex; /// The [HintType] enum is used to specify the type of hint that was received. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -32,6 +35,14 @@ pub enum HintType { L2AccountStorageProof, } +impl HintType { + /// Encodes the hint type as a string. + pub fn encode_with(&self, data: &[&[u8]]) -> String { + let concatenated = data.iter().map(hex::encode).collect::>().join(" "); + alloc::format!("{} {}", self, concatenated) + } +} + impl TryFrom<&str> for HintType { type Error = anyhow::Error; @@ -74,7 +85,7 @@ impl From for &str { } impl Display for HintType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let s: &str = (*self).into(); write!(f, "{}", s) } diff --git a/bin/programs/client/src/l1/chain_provider.rs b/bin/programs/client/src/l1/chain_provider.rs new file mode 100644 index 000000000..5ae188890 --- /dev/null +++ b/bin/programs/client/src/l1/chain_provider.rs @@ -0,0 +1,141 @@ +//! Contains the concrete implementation of the [ChainProvider] trait for the client program. + +use crate::{BootInfo, CachingOracle, HintType, HINT_WRITER}; +use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use alloy_consensus::{Header, Receipt, ReceiptEnvelope, TxEnvelope}; +use alloy_eips::eip2718::Decodable2718; +use alloy_primitives::{Bytes, B256}; +use alloy_rlp::Decodable; +use anyhow::{anyhow, Result}; +use async_trait::async_trait; +use kona_derive::traits::ChainProvider; +use kona_mpt::{OrderedListWalker, TrieDBFetcher}; +use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient}; +use kona_primitives::BlockInfo; + +/// The oracle-backed L1 chain provider for the client program. +#[derive(Debug)] +pub struct OracleL1ChainProvider { + /// The boot information + boot_info: Arc, + /// The preimage oracle client. + oracle: Arc, +} + +impl OracleL1ChainProvider { + /// Creates a new [OracleL1ChainProvider] with the given boot information and oracle client. + pub fn new(boot_info: Arc, oracle: Arc) -> Self { + Self { boot_info, oracle } + } +} + +#[async_trait] +impl ChainProvider for OracleL1ChainProvider { + async fn header_by_hash(&mut self, hash: B256) -> Result
{ + // Send a hint for the block header. + HINT_WRITER.write(&HintType::L1BlockHeader.encode_with(&[hash.as_ref()])).await?; + + // Fetch the header RLP from the oracle. + let header_rlp = + self.oracle.get(PreimageKey::new(*hash, PreimageKeyType::Keccak256)).await?; + + // Decode the header RLP into a Header. + Header::decode(&mut header_rlp.as_slice()) + .map_err(|e| anyhow!("Failed to decode header RLP: {e}")) + } + + async fn block_info_by_number(&mut self, block_number: u64) -> Result { + // Fetch the starting block header. + let mut header = self.header_by_hash(self.boot_info.l1_head).await?; + + // Check if the block number is in range. If not, we can fail early. + if block_number > header.number { + anyhow::bail!("Block number past L1 head."); + } + + // Walk back the block headers to the desired block number. + while header.number > block_number { + header = self.header_by_hash(header.parent_hash).await?; + } + + Ok(BlockInfo { + hash: header.hash_slow(), + number: header.number, + parent_hash: header.parent_hash, + timestamp: header.timestamp, + }) + } + + async fn receipts_by_hash(&mut self, hash: B256) -> Result> { + // Fetch the block header to find the receipts root. + let header = self.header_by_hash(hash).await?; + + // Send a hint for the block's receipts, and walk through the receipts trie in the header to + // verify them. + HINT_WRITER.write(&HintType::L1Receipts.encode_with(&[hash.as_ref()])).await?; + let trie_walker = OrderedListWalker::try_new_hydrated(header.receipts_root, self)?; + + // Decode the receipts within the transactions trie. + let receipts = trie_walker + .into_iter() + .map(|(_, rlp)| { + let envelope = ReceiptEnvelope::decode_2718(&mut rlp.as_ref()) + .map_err(|e| anyhow!("Failed to decode ReceiptEnvelope RLP: {e}"))?; + Ok(envelope.as_receipt().expect("Infalliable").clone()) + }) + .collect::>>()?; + + Ok(receipts) + } + + async fn block_info_and_transactions_by_hash( + &mut self, + hash: B256, + ) -> Result<(BlockInfo, Vec)> { + // Fetch the block header to construct the block info. + let header = self.header_by_hash(hash).await?; + let block_info = BlockInfo { + hash, + number: header.number, + parent_hash: header.parent_hash, + timestamp: header.timestamp, + }; + + // Send a hint for the block's transactions, and walk through the transactions trie in the + // header to verify them. + HINT_WRITER.write(&HintType::L1Transactions.encode_with(&[hash.as_ref()])).await?; + let trie_walker = OrderedListWalker::try_new_hydrated(header.transactions_root, self)?; + + // Decode the transactions within the transactions trie. + let transactions = trie_walker + .into_iter() + .map(|(_, rlp)| { + TxEnvelope::decode_2718(&mut rlp.as_ref()) + .map_err(|e| anyhow!("Failed to decode TxEnvelope RLP: {e}")) + }) + .collect::>>()?; + + Ok((block_info, transactions)) + } +} + +impl TrieDBFetcher for OracleL1ChainProvider { + fn trie_node_preimage(&self, key: B256) -> Result { + // On L1, trie node preimages are stored as keccak preimage types in the oracle. We assume + // that a hint for these preimages has already been sent, prior to this call. + kona_common::block_on(async move { + self.oracle + .get(PreimageKey::new(*key, PreimageKeyType::Keccak256)) + .await + .map(Into::into) + }) + } + + fn bytecode_by_hash(&self, _: B256) -> Result { + unimplemented!("TrieDBFetcher::bytecode_by_hash unimplemented for OracleL1ChainProvider") + } + + fn header_by_hash(&self, _: B256) -> Result
{ + unimplemented!("TrieDBFetcher::header_by_hash unimplemented for OracleL1ChainProvider") + } +} diff --git a/bin/programs/client/src/l1/mod.rs b/bin/programs/client/src/l1/mod.rs new file mode 100644 index 000000000..262b49a66 --- /dev/null +++ b/bin/programs/client/src/l1/mod.rs @@ -0,0 +1,4 @@ +//! Contains the L1 constructs of the client program. + +mod chain_provider; +pub use chain_provider::OracleL1ChainProvider; diff --git a/bin/programs/client/src/l2/chain_provider.rs b/bin/programs/client/src/l2/chain_provider.rs new file mode 100644 index 000000000..56fc82147 --- /dev/null +++ b/bin/programs/client/src/l2/chain_provider.rs @@ -0,0 +1,147 @@ +//! Contains the concrete implementation of the [L2ChainProvider] trait for the client program. + +use crate::{BootInfo, CachingOracle, HintType, HINT_WRITER}; +use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec}; +use alloy_consensus::Header; +use alloy_eips::eip2718::Decodable2718; +use alloy_primitives::{Bytes, B256}; +use alloy_rlp::Decodable; +use anyhow::{anyhow, Result}; +use async_trait::async_trait; +use kona_derive::traits::L2ChainProvider; +use kona_mpt::{OrderedListWalker, TrieDBFetcher}; +use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient}; +use kona_primitives::{ + L2BlockInfo, L2ExecutionPayloadEnvelope, OpBlock, RollupConfig, SystemConfig, +}; +use op_alloy_consensus::OpTxEnvelope; + +/// The oracle-backed L2 chain provider for the client program. +#[derive(Debug)] +pub struct OracleL2ChainProvider { + /// The rollup configuration. + cfg: Arc, + /// The boot information + boot_info: Arc, + /// The preimage oracle client. + oracle: Arc, +} + +impl OracleL2ChainProvider { + /// Returns a [Header] corresponding to the given L2 block number, by walking back from the + /// L2 safe head. + async fn header_by_number(&mut self, block_number: u64) -> Result
{ + // Fetch the starting L2 output preimage. + HINT_WRITER.write(&HintType::StartingL2Output.to_string()).await?; + let output_preimage = self + .oracle + .get(PreimageKey::new(*self.boot_info.l2_output_root, PreimageKeyType::Keccak256)) + .await?; + + // Fetch the starting block header. + let block_hash = output_preimage[96..128] + .try_into() + .map_err(|e| anyhow!("Failed to extract block hash from output preimage: {e}"))?; + let mut header = self.header_by_hash(block_hash)?; + + // Check if the block number is in range. If not, we can fail early. + if block_number > header.number { + anyhow::bail!("Block number past L1 head."); + } + + // Walk back the block headers to the desired block number. + while header.number > block_number { + header = self.header_by_hash(header.parent_hash)?; + } + + Ok(header) + } +} + +#[async_trait] +impl L2ChainProvider for OracleL2ChainProvider { + async fn l2_block_info_by_number(&mut self, number: u64) -> Result { + // Get the payload at the given block number. + let payload = self.payload_by_number(number).await?; + + // Construct the system config from the payload. + payload.to_l2_block_ref(self.cfg.as_ref()) + } + + async fn payload_by_number(&mut self, number: u64) -> Result { + // Fetch the header for the given block number. + let header @ Header { transactions_root, timestamp, .. } = + self.header_by_number(number).await?; + let header_hash = header.hash_slow(); + + // Fetch the transactions in the block. + HINT_WRITER.write(&HintType::L2Transactions.encode_with(&[header_hash.as_ref()])).await?; + let trie_walker = OrderedListWalker::try_new_hydrated(transactions_root, self)?; + + // Decode the transactions within the transactions trie. + let transactions = trie_walker + .into_iter() + .map(|(_, rlp)| { + OpTxEnvelope::decode_2718(&mut rlp.as_ref()) + .map_err(|e| anyhow!("Failed to decode TxEnvelope RLP: {e}")) + }) + .collect::>>()?; + + let optimism_block = OpBlock { + header, + body: transactions, + withdrawals: self.cfg.is_canyon_active(timestamp).then(Vec::new), + ..Default::default() + }; + Ok(optimism_block.into()) + } + + async fn system_config_by_number( + &mut self, + number: u64, + rollup_config: Arc, + ) -> Result { + // Get the payload at the given block number. + let payload = self.payload_by_number(number).await?; + + // Construct the system config from the payload. + payload.to_system_config(rollup_config.as_ref()) + } +} + +impl TrieDBFetcher for OracleL2ChainProvider { + fn trie_node_preimage(&self, key: B256) -> Result { + // On L2, trie node preimages are stored as keccak preimage types in the oracle. We assume + // that a hint for these preimages has already been sent, prior to this call. + kona_common::block_on(async move { + self.oracle + .get(PreimageKey::new(*key, PreimageKeyType::Keccak256)) + .await + .map(Into::into) + }) + } + + fn bytecode_by_hash(&self, hash: B256) -> Result { + // Fetch the bytecode preimage from the caching oracle. + kona_common::block_on(async move { + HINT_WRITER.write(&HintType::L2Code.encode_with(&[hash.as_ref()])).await?; + + self.oracle + .get(PreimageKey::new(*hash, PreimageKeyType::Keccak256)) + .await + .map(Into::into) + }) + } + + fn header_by_hash(&self, hash: B256) -> Result
{ + // Fetch the header from the caching oracle. + kona_common::block_on(async move { + HINT_WRITER.write(&HintType::L2BlockHeader.encode_with(&[hash.as_ref()])).await?; + + let header_bytes = + self.oracle.get(PreimageKey::new(*hash, PreimageKeyType::Keccak256)).await?; + Header::decode(&mut header_bytes.as_slice()) + .map_err(|e| anyhow!("Failed to RLP decode Header: {e}")) + }) + } +} diff --git a/bin/programs/client/src/l2/executor/fetcher.rs b/bin/programs/client/src/l2/executor/fetcher.rs deleted file mode 100644 index 7cd10be43..000000000 --- a/bin/programs/client/src/l2/executor/fetcher.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! Contains the fetcher construction functions for the block executor's [TrieDB]. -//! -//! [TrieDB]: kona_mpt::TrieDB - -use crate::{CachingOracle, HINT_WRITER}; -use alloy_consensus::Header; -use alloy_primitives::{hex, Address, Bytes, B256}; -use alloy_rlp::Decodable; -use anyhow::{anyhow, Result}; -use kona_mpt::{TrieDBFetcher, TrieDBHinter}; -use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient}; - -/// The [TrieDBFetcher] implementation for the block executor's [TrieDB]. -/// -/// TODO: Move this into the higher-level L2 chain fetcher, and also implement the [TrieDBFetcher] -/// trait. -/// -/// [TrieDB]: kona_mpt::TrieDB -#[derive(Debug)] -pub struct TrieDBProvider<'a, const N: usize> { - /// The inner caching oracle to fetch trie node preimages from. - caching_oracle: &'a CachingOracle, -} - -impl<'a, const N: usize> TrieDBProvider<'a, N> { - /// Constructs a new [TrieDBProvider] with the given [CachingOracle]. - pub fn new(caching_oracle: &'a CachingOracle) -> Self { - Self { caching_oracle } - } -} - -impl<'a, const N: usize> TrieDBFetcher for TrieDBProvider<'a, N> { - fn trie_node_preimage(&self, key: B256) -> Result { - // Fetch the trie preimage from the caching oracle. - kona_common::block_on(async move { - self.caching_oracle - .get(PreimageKey::new(*key, PreimageKeyType::Keccak256)) - .await - .map(Into::into) - }) - } - - fn bytecode_by_hash(&self, _: B256) -> Result { - todo!() - } - - fn header_by_hash(&self, hash: B256) -> Result
{ - // Fetch the header from the caching oracle. - kona_common::block_on(async move { - let header_bytes = self - .caching_oracle - .get(PreimageKey::new(*hash, PreimageKeyType::Keccak256)) - .await?; - Header::decode(&mut header_bytes.as_slice()) - .map_err(|e| anyhow!("Failed to RLP decode Header: {e}")) - }) - } -} - -/// The [TrieDBHinter] implementation for the block executor's [TrieDB]. -/// -/// [TrieDB]: kona_mpt::TrieDB -#[derive(Debug)] -pub struct TrieDBHintWriter; - -impl TrieDBHinter for TrieDBHintWriter { - fn hint_trie_node(&self, hash: B256) -> Result<()> { - kona_common::block_on(async move { - HINT_WRITER - .write(&alloc::format!("l2-state-node {}", hex::encode(hash.as_slice()))) - .await - }) - } - - fn hint_account_proof(&self, address: Address, block_number: u64) -> Result<()> { - kona_common::block_on(async move { - HINT_WRITER - .write(&alloc::format!( - "l2-account-proof {}{}", - hex::encode(block_number.to_be_bytes()), - hex::encode(address.as_slice()) - )) - .await - }) - } - - fn hint_storage_proof( - &self, - address: alloy_primitives::Address, - slot: alloy_primitives::U256, - block_number: u64, - ) -> Result<()> { - kona_common::block_on(async move { - HINT_WRITER - .write(&alloc::format!( - "l2-account-storage-proof {}{}{}", - hex::encode(block_number.to_be_bytes()), - hex::encode(address.as_slice()), - hex::encode(slot.to_be_bytes::<32>()) - )) - .await - }) - } -} diff --git a/bin/programs/client/src/l2/executor/hinter.rs b/bin/programs/client/src/l2/executor/hinter.rs new file mode 100644 index 000000000..53e9ecf7d --- /dev/null +++ b/bin/programs/client/src/l2/executor/hinter.rs @@ -0,0 +1,51 @@ +//! Contains the hinter for the [TrieDB]. +//! +//! [TrieDB]: kona_mpt::TrieDB + +use crate::{HintType, HINT_WRITER}; +use alloy_primitives::{Address, B256}; +use anyhow::Result; +use kona_mpt::TrieDBHinter; +use kona_preimage::HintWriterClient; + +/// The [TrieDBHinter] implementation for the block executor's [TrieDB]. +/// +/// [TrieDB]: kona_mpt::TrieDB +#[derive(Debug)] +pub struct TrieDBHintWriter; + +impl TrieDBHinter for TrieDBHintWriter { + fn hint_trie_node(&self, hash: B256) -> Result<()> { + kona_common::block_on(async move { + HINT_WRITER.write(&HintType::L2StateNode.encode_with(&[hash.as_slice()])).await + }) + } + + fn hint_account_proof(&self, address: Address, block_number: u64) -> Result<()> { + kona_common::block_on(async move { + HINT_WRITER + .write( + &HintType::L2AccountProof + .encode_with(&[block_number.to_be_bytes().as_ref(), address.as_slice()]), + ) + .await + }) + } + + fn hint_storage_proof( + &self, + address: alloy_primitives::Address, + slot: alloy_primitives::U256, + block_number: u64, + ) -> Result<()> { + kona_common::block_on(async move { + HINT_WRITER + .write(&HintType::L2AccountStorageProof.encode_with(&[ + block_number.to_be_bytes().as_ref(), + address.as_slice(), + slot.to_be_bytes::<32>().as_ref(), + ])) + .await + }) + } +} diff --git a/bin/programs/client/src/l2/executor/mod.rs b/bin/programs/client/src/l2/executor/mod.rs index 9a693946d..c6c9dd10d 100644 --- a/bin/programs/client/src/l2/executor/mod.rs +++ b/bin/programs/client/src/l2/executor/mod.rs @@ -18,8 +18,8 @@ use revm::{ Evm, StateBuilder, }; -mod fetcher; -pub use fetcher::{TrieDBHintWriter, TrieDBProvider}; +mod hinter; +pub use hinter::TrieDBHintWriter; mod eip4788; pub(crate) use eip4788::pre_block_beacon_root_contract_call; diff --git a/bin/programs/client/src/l2/mod.rs b/bin/programs/client/src/l2/mod.rs index c0c13b8ba..3b945c441 100644 --- a/bin/programs/client/src/l2/mod.rs +++ b/bin/programs/client/src/l2/mod.rs @@ -2,4 +2,7 @@ //! [StatelessL2BlockExecutor] mod executor; -pub use executor::{StatelessL2BlockExecutor, TrieDBHintWriter, TrieDBProvider}; +pub use executor::{StatelessL2BlockExecutor, TrieDBHintWriter}; + +mod chain_provider; +pub use chain_provider::OracleL2ChainProvider; diff --git a/bin/programs/client/src/lib.rs b/bin/programs/client/src/lib.rs index e4ef5a6e0..668e22643 100644 --- a/bin/programs/client/src/lib.rs +++ b/bin/programs/client/src/lib.rs @@ -6,8 +6,13 @@ extern crate alloc; +pub mod l1; + pub mod l2; +pub mod hint; +pub use hint::HintType; + mod comms; pub use comms::{CachingOracle, HINT_WRITER, ORACLE_READER}; diff --git a/bin/programs/client/src/main.rs b/bin/programs/client/src/main.rs index ba152ab7b..aa0e03170 100644 --- a/bin/programs/client/src/main.rs +++ b/bin/programs/client/src/main.rs @@ -11,10 +11,13 @@ use kona_common_proc::client_entry; extern crate alloc; +/// The size of the LRU cache in the oracle. +const ORACLE_LRU_SIZE: usize = 16; + #[client_entry(0x77359400)] fn main() -> Result<()> { kona_common::block_on(async move { - let caching_oracle = CachingOracle::<16>::new(); + let caching_oracle = CachingOracle::new(ORACLE_LRU_SIZE); let boot = BootInfo::load(&caching_oracle).await?; io::print(&alloc::format!("{:?}\n", boot)); Ok::<_, anyhow::Error>(()) diff --git a/crates/mpt/src/list_walker.rs b/crates/mpt/src/list_walker.rs index d7ccafee3..f98c82af4 100644 --- a/crates/mpt/src/list_walker.rs +++ b/crates/mpt/src/list_walker.rs @@ -140,7 +140,13 @@ where fn next(&mut self) -> Option { match self.inner { - Some(ref mut leaves) => leaves.pop_front(), + Some(ref mut leaves) => { + let item = leaves.pop_front(); + if leaves.is_empty() { + self.inner = None; + } + item + } _ => None, } } diff --git a/crates/mpt/src/util.rs b/crates/mpt/src/util.rs index bbfd9902a..7be1884e6 100644 --- a/crates/mpt/src/util.rs +++ b/crates/mpt/src/util.rs @@ -16,9 +16,9 @@ where // Store preimages for all intermediates let path_nibbles = (0..items_len) .map(|i| { - let i = adjust_index_for_rlp(i, items_len); + let index = adjust_index_for_rlp(i, items_len); index_buffer.clear(); - i.encode(&mut index_buffer); + index.encode(&mut index_buffer); Nibbles::unpack(&index_buffer) }) .collect::>();