Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions crates/derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![no_std]
// Temp
#![allow(dead_code, unused, unreachable_pub)]

extern crate alloc;

pub mod params;
mod params;
pub use params::{
ChannelID, CHANNEL_ID_LENGTH, DERIVATION_VERSION_0, FRAME_OVERHEAD, MAX_CHANNEL_BANK_SIZE,
MAX_RLP_BYTES_PER_CHANNEL, MAX_SPAN_BATCH_BYTES,
};

pub mod stages;
pub mod traits;
pub mod types;
Expand Down
27 changes: 13 additions & 14 deletions crates/derive/src/stages/channel_bank.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
//! This module contains the `ChannelBank` struct.

use super::{frame_queue::FrameQueue, l1_retrieval::L1Retrieval};
use super::frame_queue::FrameQueue;
use crate::{
params::{ChannelID, MAX_CHANNEL_BANK_SIZE},
traits::{ChainProvider, DataAvailabilityProvider, ResettableStage},
types::{BlockInfo, Channel, Frame, RollupConfig, StageError, StageResult, SystemConfig},
};
use alloc::{boxed::Box, collections::VecDeque};
use alloy_primitives::Bytes;
use anyhow::{anyhow, bail};
use anyhow::anyhow;
use async_trait::async_trait;
use core::fmt::Debug;
use hashbrown::HashMap;

/// [ChannelBank] is a stateful stage that does the following:
Expand All @@ -23,10 +24,11 @@ use hashbrown::HashMap;
/// Specifically, the channel bank is not allowed to become too large between successive calls
/// to `IngestData`. This means that we can do an ingest and then do a read while becoming too large.
/// [ChannelBank] buffers channel frames, and emits full channel data
#[derive(Debug)]
pub struct ChannelBank<DAP, CP>
where
DAP: DataAvailabilityProvider,
CP: ChainProvider,
DAP: DataAvailabilityProvider + Debug,
CP: ChainProvider + Debug,
{
/// The rollup configuration.
cfg: RollupConfig,
Expand All @@ -36,23 +38,20 @@ where
channel_queue: VecDeque<ChannelID>,
/// The previous stage of the derivation pipeline.
prev: FrameQueue<DAP, CP>,
/// Chain provider.
chain_provider: CP,
}

impl<DAP, CP> ChannelBank<DAP, CP>
where
DAP: DataAvailabilityProvider,
CP: ChainProvider,
DAP: DataAvailabilityProvider + Debug,
CP: ChainProvider + Debug,
{
/// Create a new [ChannelBank] stage.
pub fn new(cfg: RollupConfig, prev: FrameQueue<DAP, CP>, chain_provider: CP) -> Self {
pub fn new(cfg: RollupConfig, prev: FrameQueue<DAP, CP>) -> Self {
Self {
cfg,
channels: HashMap::new(),
channel_queue: VecDeque::new(),
prev,
chain_provider,
}
}

Expand Down Expand Up @@ -162,7 +161,7 @@ where

// Load the data into the channel bank
let frame = self.prev.next_frame().await?;
self.ingest_frame(frame);
self.ingest_frame(frame)?;
Err(StageError::NotEnoughData)
}

Expand Down Expand Up @@ -193,10 +192,10 @@ where
#[async_trait]
impl<DAP, CP> ResettableStage for ChannelBank<DAP, CP>
where
DAP: DataAvailabilityProvider + Send,
CP: ChainProvider + Send,
DAP: DataAvailabilityProvider + Send + Debug,
CP: ChainProvider + Send + Debug,
{
async fn reset(&mut self, base: BlockInfo, cfg: SystemConfig) -> StageResult<()> {
async fn reset(&mut self, _: BlockInfo, _: SystemConfig) -> StageResult<()> {
self.channels.clear();
self.channel_queue = VecDeque::with_capacity(10);
Err(StageError::Eof)
Expand Down
21 changes: 12 additions & 9 deletions crates/derive/src/stages/frame_queue.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
//! This module contains the [FrameQueue] stage of the derivation pipeline.

use core::fmt::Debug;

use super::l1_retrieval::L1Retrieval;
use crate::{
traits::{ChainProvider, DataAvailabilityProvider, ResettableStage},
types::{BlockInfo, Frame, StageError, StageResult, SystemConfig},
};
use alloc::{boxed::Box, collections::VecDeque};
use alloy_primitives::Bytes;
use anyhow::{anyhow, bail, Result};
use anyhow::anyhow;
use async_trait::async_trait;

/// The frame queue stage of the derivation pipeline.
#[derive(Debug)]
pub struct FrameQueue<DAP, CP>
where
DAP: DataAvailabilityProvider,
CP: ChainProvider,
DAP: DataAvailabilityProvider + Debug,
CP: ChainProvider + Debug,
{
/// The previous stage in the pipeline.
pub prev: L1Retrieval<DAP, CP>,
Expand All @@ -23,8 +26,8 @@ where

impl<DAP, CP> FrameQueue<DAP, CP>
where
DAP: DataAvailabilityProvider,
CP: ChainProvider,
DAP: DataAvailabilityProvider + Debug,
CP: ChainProvider + Debug,
{
/// Create a new frame queue stage.
pub fn new(prev: L1Retrieval<DAP, CP>) -> Self {
Expand Down Expand Up @@ -67,10 +70,10 @@ where
#[async_trait]
impl<DAP, CP> ResettableStage for FrameQueue<DAP, CP>
where
DAP: DataAvailabilityProvider + Send,
CP: ChainProvider + Send,
DAP: DataAvailabilityProvider + Send + Debug,
CP: ChainProvider + Send + Debug,
{
async fn reset(&mut self, base: BlockInfo, cfg: SystemConfig) -> StageResult<()> {
async fn reset(&mut self, _: BlockInfo, _: SystemConfig) -> StageResult<()> {
self.queue = VecDeque::default();
Err(StageError::Eof)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/derive/src/stages/l1_retrieval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
traits::{ChainProvider, DataAvailabilityProvider, DataIter, ResettableStage},
types::{BlockInfo, StageError, StageResult, SystemConfig},
};
use alloc::{boxed::Box, vec::Vec};
use alloc::boxed::Box;
use alloy_primitives::Bytes;
use anyhow::anyhow;
use async_trait::async_trait;
Expand Down
2 changes: 1 addition & 1 deletion crates/derive/src/stages/l1_traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
types::{BlockInfo, RollupConfig, StageError, StageResult, SystemConfig},
};
use alloc::boxed::Box;
use anyhow::{anyhow, bail};
use anyhow::anyhow;
use async_trait::async_trait;

/// The L1 traversal stage of the derivation pipeline.
Expand Down
12 changes: 9 additions & 3 deletions crates/derive/src/stages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@
mod l1_traversal;
pub use l1_traversal::L1Traversal;

mod batch_queue;
mod l1_retrieval;
pub use l1_retrieval::L1Retrieval;

mod frame_queue;
pub use frame_queue::FrameQueue;

mod channel_bank;
pub use channel_bank::ChannelBank;

mod batch_queue;
mod channel_reader;
mod engine_queue;
mod frame_queue;
mod l1_retrieval;
mod payload_derivation;
4 changes: 2 additions & 2 deletions crates/derive/src/traits/data_sources.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Contains traits that describe the functionality of various data sources used in the derivation pipeline's stages.

// use alloy_rpc_types::Block;
use crate::types::{BlockInfo, Receipt, StageResult};
use alloc::{boxed::Box, vec::Vec};
use alloy_primitives::{Address, Bytes, B256};
use anyhow::Result;
use async_trait::async_trait;
use core::fmt::Debug;

/// Describes the functionality of a data source that can provide information from the blockchain.
#[async_trait]
Expand All @@ -22,7 +22,7 @@ pub trait ChainProvider {
#[async_trait]
pub trait DataAvailabilityProvider {
/// A data iterator for the data source to return.
type DataIter<T: Into<Bytes>>: DataIter<T> + Send;
type DataIter<T: Into<Bytes>>: DataIter<T> + Send + Debug;

/// Returns the data availability for the block with the given hash, or an error if the block does not exist in the
/// data source.
Expand Down
9 changes: 5 additions & 4 deletions crates/derive/src/types/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,10 @@ impl Channel {

#[cfg(test)]
mod test {
use std::println;

use super::Channel;
use crate::{
params::ChannelID,
types::{BlockInfo, Frame},
};
use crate::types::{BlockInfo, Frame};
use alloc::{
string::{String, ToString},
vec,
Expand All @@ -178,6 +177,8 @@ mod test {
}

fn run_frame_validity_test(test_case: FrameValidityTestCase) {
println!("Running test: {}", test_case.name);

let id = [0xFF; 16];
let block = BlockInfo::default();
let mut channel = Channel::new(id, block);
Expand Down
2 changes: 2 additions & 0 deletions crates/derive/src/types/eips/merge.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Constants related to the beacon chain consensus.

#![allow(unreachable_pub, unused)]

/// An EPOCH is a series of 32 slots.
pub const EPOCH_SLOTS: u64 = 32;

Expand Down
5 changes: 5 additions & 0 deletions crates/derive/src/types/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ impl Frame {
.try_into()
.map_err(|e| anyhow!("Error: {e}"))?,
) as usize;

if data_len > MAX_FRAME_LEN {
bail!("Frame data too large");
}

let data = encoded[22..22 + data_len].to_vec();
let is_last = encoded[22 + data_len] != 0;
Ok((
Expand Down
2 changes: 1 addition & 1 deletion crates/derive/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module contains all of the types used within the derivation pipeline.

mod system_config;
pub use system_config::{SystemAccounts, SystemConfig};
pub use system_config::{SystemAccounts, SystemConfig, SystemConfigUpdateType};

mod rollup_config;
pub use rollup_config::RollupConfig;
Expand Down
2 changes: 2 additions & 0 deletions crates/derive/src/types/network/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! `alloy-network` crate ported to `no_std`.

#![allow(unused, unreachable_pub)]

use crate::types::eips::eip2718::Eip2718Envelope;
use alloc::vec::Vec;
use alloy_primitives::B256;
Expand Down
28 changes: 16 additions & 12 deletions crates/derive/src/types/system_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::{Receipt, RollupConfig};
use alloy_primitives::{address, b256, Address, Log, B256, U256};
use alloy_sol_types::{sol, SolType, SolValue};
use alloy_sol_types::{sol, SolType};
use anyhow::{anyhow, bail, Result};

/// `keccak256("ConfigUpdate(uint256,uint8,bytes)")`
Expand Down Expand Up @@ -35,9 +35,13 @@ pub struct SystemConfig {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u64)]
pub enum SystemConfigUpdateType {
/// Batcher update type
Batcher = 0,
/// Gas config update type
GasConfig = 1,
/// Gas limit update type
GasLimit = 2,
/// Unsafe block signer update type
UnsafeBlockSigner = 3,
}

Expand Down Expand Up @@ -125,19 +129,19 @@ impl SystemConfig {
}

let pointer = <sol!(uint64)>::abi_decode(&log_data[0..32], true)
.map_err(|e| anyhow!("Failed to decode batcher update log"))?;
.map_err(|_| anyhow!("Failed to decode batcher update log"))?;
if pointer != 32 {
bail!("Invalid config update log: invalid data pointer");
}
let length = <sol!(uint64)>::abi_decode(&log_data[32..64], true)
.map_err(|e| anyhow!("Failed to decode batcher update log"))?;
.map_err(|_| anyhow!("Failed to decode batcher update log"))?;
if length != 32 {
bail!("Invalid config update log: invalid data length");
}

let batcher_address =
<sol!(address)>::abi_decode(&log.data.data.as_ref()[64..], true)
.map_err(|e| anyhow!("Failed to decode batcher update log"))?;
.map_err(|_| anyhow!("Failed to decode batcher update log"))?;
self.batcher_addr = batcher_address;
}
SystemConfigUpdateType::GasConfig => {
Expand All @@ -146,20 +150,20 @@ impl SystemConfig {
}

let pointer = <sol!(uint64)>::abi_decode(&log_data[0..32], true)
.map_err(|e| anyhow!("Invalid config update log: invalid data pointer"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid data pointer"))?;
if pointer != 32 {
bail!("Invalid config update log: invalid data pointer");
}
let length = <sol!(uint64)>::abi_decode(&log_data[32..64], true)
.map_err(|e| anyhow!("Invalid config update log: invalid data length"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid data length"))?;
if length != 64 {
bail!("Invalid config update log: invalid data length");
}

let overhead = <sol!(uint256)>::abi_decode(&log_data[64..96], true)
.map_err(|e| anyhow!("Invalid config update log: invalid overhead"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid overhead"))?;
let scalar = <sol!(uint256)>::abi_decode(&log_data[96..], true)
.map_err(|e| anyhow!("Invalid config update log: invalid scalar"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid scalar"))?;

if rollup_config.is_ecotone_active(l1_time) {
if RollupConfig::check_ecotone_l1_system_config_scalar(scalar.to_be_bytes())
Expand All @@ -184,18 +188,18 @@ impl SystemConfig {
}

let pointer = <sol!(uint64)>::abi_decode(&log_data[0..32], true)
.map_err(|e| anyhow!("Invalid config update log: invalid data pointer"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid data pointer"))?;
if pointer != 32 {
bail!("Invalid config update log: invalid data pointer");
}
let length = <sol!(uint64)>::abi_decode(&log_data[32..64], true)
.map_err(|e| anyhow!("Invalid config update log: invalid data length"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid data length"))?;
if length != 32 {
bail!("Invalid config update log: invalid data length");
}

let gas_limit = <sol!(uint256)>::abi_decode(&log_data[64..], true)
.map_err(|e| anyhow!("Invalid config update log: invalid gas limit"))?;
.map_err(|_| anyhow!("Invalid config update log: invalid gas limit"))?;
self.gas_limit = gas_limit;
}
SystemConfigUpdateType::UnsafeBlockSigner => {
Expand Down Expand Up @@ -235,7 +239,7 @@ mod test {

use super::*;
use alloc::vec;
use alloy_primitives::{hex, Bytes, LogData};
use alloy_primitives::{hex, LogData};

extern crate std;

Expand Down
Loading