diff --git a/Cargo.lock b/Cargo.lock index 31e1f38..17434b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3380,7 +3380,11 @@ dependencies = [ name = "kona-providers" version = "0.0.0" dependencies = [ + "async-trait", + "eyre", "kona-derive", + "parking_lot 0.12.3", + "reth", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b1a6126..553f244 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -148,3 +148,6 @@ reth-tracing = { git = "https://github.com/paradigmxyz/reth", version = "1.0.5" tracing = "0.1.0" eyre = "0.6.12" clap = "4" +async-trait = "0.1.81" +hashbrown = "0.14.5" +parking_lot = "0.12.3" diff --git a/crates/kona-providers/Cargo.toml b/crates/kona-providers/Cargo.toml index a0f3288..2b70c67 100644 --- a/crates/kona-providers/Cargo.toml +++ b/crates/kona-providers/Cargo.toml @@ -11,6 +11,10 @@ keywords.workspace = true categories.workspace = true [dependencies] +reth.workspace = true +async-trait.workspace = true +parking_lot.workspace = true +eyre.workspace = true kona-derive.workspace = true [features] diff --git a/crates/kona-providers/src/chain_provider.rs b/crates/kona-providers/src/chain_provider.rs new file mode 100644 index 0000000..8a9ea19 --- /dev/null +++ b/crates/kona-providers/src/chain_provider.rs @@ -0,0 +1,66 @@ +//! Chain Provider + +use alloc::{collections::vec_deque::VecDeque, sync::Arc}; +use hashbrown::HashMap; + +use async_trait::async_trait; +use eyre::Result; +use kona_derive::{ + traits::ChainProvider, + types::{ + alloy_primitives::B256, BlockID, BlockInfo, Header, Receipt, Signed, TxEip1559, TxEip2930, + TxEip4844, TxEip4844Variant, TxEnvelope, TxLegacy, + }, +}; +use parking_lot::RwLock; +use reth::{primitives::Transaction, providers::Chain}; + +/// An in-memory [ChainProvider] that stores chain data, +/// meant to be shared between multiple readers. +/// +/// This provider is implemented with `FIFOMap`s to avoid +/// storing an unbounded amount of data. +#[derive(Debug, Clone)] +pub struct InMemoryChainProvider(Arc>); + +impl InMemoryChainProvider { + /// Create a new [InMemoryChainProvider] with the given capacity. + pub fn with_capacity(cap: usize) -> Self { + Self(Arc::new(RwLock::new(InMemoryChainProviderInner::with_capacity(cap)))) + } + + /// Commits Chain state to the provider. + pub fn commit(&mut self, chain: Arc) { + self.0.write().commit(chain); + } + + /// Inserts the L2 genesis [BlockID] into the provider. + pub fn insert_l2_genesis_block(&mut self, block: BlockID) { + self.0.write().insert_l2_genesis_block(block); + } +} + +/// The inner state of an [InMemoryChainProvider]. +#[derive(Debug)] +pub struct InMemoryChainProviderInner { + /// The maximum number of items to store in the provider. + /// This is used to prevent unbounded memory usage. + capacity: usize, + + /// The order in which keys were inserted into the provider. + /// This is used to evict the oldest items when the provider + /// reaches its capacity. + key_order: VecDeque, + + /// Maps [B256] hash to [Header]. + hash_to_header: HashMap, + + /// Maps [B256] hash to [BlockInfo]. + hash_to_block_info: HashMap, + + /// Maps [B256] hash to [Vec]<[Receipt]>. + hash_to_receipts: HashMap>, + + /// Maps a [B256] hash to a [Vec]<[TxEnvelope]>. + hash_to_txs: HashMap>, +} diff --git a/crates/kona-providers/src/lib.rs b/crates/kona-providers/src/lib.rs index 52e1117..6d3d22b 100644 --- a/crates/kona-providers/src/lib.rs +++ b/crates/kona-providers/src/lib.rs @@ -9,3 +9,6 @@ extern crate alloc; /// Re-export kona's derivation traits pub use kona_derive::traits::*; + +pub mod chain_provider; +pub use chain_provider::{InMemoryChainProvider, InnerChainProvider};