diff --git a/crates/derive/src/stages/l1_retrieval.rs b/crates/derive/src/stages/l1_retrieval.rs index 8b1378917..dfafac204 100644 --- a/crates/derive/src/stages/l1_retrieval.rs +++ b/crates/derive/src/stages/l1_retrieval.rs @@ -1 +1,72 @@ +//! Contains the [L1Retrieval] stage of the derivation pipeline.] +use super::L1Traversal; +use crate::{ + traits::{ChainProvider, DataAvailabilityProvider, DataIter, ResettableStage}, + types::{BlockInfo, SystemConfig}, +}; +use alloc::boxed::Box; +use alloy_primitives::Bytes; +use anyhow::{anyhow, Result}; +use async_trait::async_trait; + +/// The L1 retrieval stage of the derivation pipeline. +#[derive(Debug)] +pub struct L1Retrieval +where + DAP: DataAvailabilityProvider, + CP: ChainProvider, +{ + /// The previous stage in the pipeline. + pub prev: L1Traversal, + /// The data availability provider to use for the L1 retrieval stage. + pub provider: DAP, + /// The current data iterator. + data: Option>, +} + +impl L1Retrieval +where + T: Into, + DAP: DataAvailabilityProvider, + CP: ChainProvider, +{ + /// Creates a new L1 retrieval stage with the given data availability provider and previous stage. + pub fn new(prev: L1Traversal, provider: DAP) -> Self { + Self { + prev, + provider, + data: None, + } + } + + /// Returns the current L1 block in the traversal stage, if it exists. + pub fn origin(&self) -> Option<&BlockInfo> { + self.prev.origin() + } + + /// Retrieves the next data item from the L1 retrieval stage. + /// If there is data, it pushes it into the next stage. + /// If there is no data, it returns an error. + pub async fn next_data(&mut self) -> Result { + if self.data.is_none() { + let next = self + .prev + .next_l1_block() + .ok_or_else(|| anyhow!("No block to retrieve data from"))?; + self.data = Some( + self.provider + .open_data(&next, self.prev.system_config.batch_sender) + .await?, + ); + } + + // Fetch next data item from the iterator. + let data = self + .data + .as_mut() + .and_then(|d| d.next()) + .ok_or_else(|| anyhow!("No more data to retrieve"))?; + Ok(data.into()) + } +} diff --git a/crates/derive/src/stages/l1_traversal.rs b/crates/derive/src/stages/l1_traversal.rs index 1e7cad4c6..fd6a0c0b9 100644 --- a/crates/derive/src/stages/l1_traversal.rs +++ b/crates/derive/src/stages/l1_traversal.rs @@ -16,9 +16,9 @@ pub struct L1Traversal { /// Signals whether or not the traversal stage has been completed. done: bool, /// The system config - system_config: SystemConfig, + pub system_config: SystemConfig, /// The rollup config - rollup_config: RollupConfig, + pub rollup_config: RollupConfig, } impl L1Traversal { @@ -44,6 +44,11 @@ impl L1Traversal { } } + /// Returns the current L1 block in the traversal stage, if it exists. + pub fn origin(&self) -> Option<&BlockInfo> { + self.block.as_ref() + } + /// Advances the internal state of the [L1Traversal] stage to the next L1 block. pub async fn advance_l1_block(&mut self) -> Result<()> { let block = self.block.ok_or(anyhow!("No block to advance from"))?; diff --git a/crates/derive/src/traits/data_sources.rs b/crates/derive/src/traits/data_sources.rs index e5e406fb9..c9e56bfc2 100644 --- a/crates/derive/src/traits/data_sources.rs +++ b/crates/derive/src/traits/data_sources.rs @@ -3,7 +3,7 @@ // use alloy_rpc_types::Block; use crate::types::{BlockInfo, Receipt}; use alloc::{boxed::Box, vec::Vec}; -use alloy_primitives::B256; +use alloy_primitives::{Address, B256}; use anyhow::Result; use async_trait::async_trait; @@ -17,3 +17,24 @@ pub trait ChainProvider { /// source. async fn receipts_by_hash(&self, hash: B256) -> Result>; } + +/// Describes the functionality of a data source that can provide data availability information. +#[async_trait] +pub trait DataAvailabilityProvider { + /// A data iterator for the data source to return. + type DataIter: DataIter; + + /// Returns the data availability for the block with the given hash, or an error if the block does not exist in the + /// data source. + async fn open_data( + &self, + block_ref: &BlockInfo, + batcher_address: Address, + ) -> Result>; +} + +/// Describes the behavior of a data iterator. +pub trait DataIter { + /// Returns the next item in the iterator, or `None` if the iterator is exhausted. + fn next(&self) -> Option; +} diff --git a/crates/derive/src/traits/mod.rs b/crates/derive/src/traits/mod.rs index f4b2f960b..a1c2b46fe 100644 --- a/crates/derive/src/traits/mod.rs +++ b/crates/derive/src/traits/mod.rs @@ -1,7 +1,7 @@ //! This module contains all of the traits describing functionality of portions of the derivation pipeline. mod data_sources; -pub use data_sources::ChainProvider; +pub use data_sources::{ChainProvider, DataAvailabilityProvider, DataIter}; mod stages; pub use stages::ResettableStage; diff --git a/crates/derive/src/traits/stages.rs b/crates/derive/src/traits/stages.rs index 70f42deeb..1bf6d3030 100644 --- a/crates/derive/src/traits/stages.rs +++ b/crates/derive/src/traits/stages.rs @@ -1,8 +1,7 @@ //! This module contains common traits for stages within the derivation pipeline. -use anyhow::Result; - use crate::types::{BlockInfo, SystemConfig}; +use anyhow::Result; /// Describes the functionality fo a resettable stage within the derivation pipeline. pub trait ResettableStage {