Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
8 changes: 8 additions & 0 deletions crates/derivation-pipeline/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ pub enum DerivationPipelineError {
/// Missing L1 message.
#[error("missing l1 message for L2 block {0:?}")]
MissingL1Message(L2Block),
/// Blocks are not contiguous
#[error("loss of contiguity in blocks: expected {expected}, got {got}")]
BlockDiscontinuity {
/// The expected block number.
expected: u64,
/// The actual block number.
got: u64,
},
/// Unknown batch.
#[error("unknown batch for index {0}")]
UnknownBatch(u64),
Expand Down
194 changes: 121 additions & 73 deletions crates/derivation-pipeline/src/lib.rs

Large diffs are not rendered by default.

20 changes: 9 additions & 11 deletions crates/engine/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use crate::{
use alloy_provider::Provider;
use futures::{ready, task::AtomicWaker, FutureExt, Stream};
use rollup_node_primitives::{
BlockInfo, ChainImport, MeteredFuture, ScrollPayloadAttributesWithBatchInfo, WithBlockNumber,
BlockInfo, ChainImport, MeteredFuture, WithFullL2Meta, WithL1FinalizedBlockNumber,
WithL2BlockNumber,
};
use scroll_alloy_hardforks::ScrollHardforks;
use scroll_alloy_network::Scroll;
Expand Down Expand Up @@ -38,7 +39,7 @@ pub struct EngineDriver<EC, CS, P> {
/// Block building duration.
block_building_duration: Duration,
/// The pending payload attributes derived from batches on L1.
l1_payload_attributes: VecDeque<WithBlockNumber<ScrollPayloadAttributesWithBatchInfo>>,
l1_payload_attributes: VecDeque<WithFullL2Meta<ScrollPayloadAttributes>>,
/// The pending block imports received over the network.
chain_imports: VecDeque<ChainImport>,
/// The latest optimistic sync target.
Expand Down Expand Up @@ -158,8 +159,8 @@ where
// L2 reorged number.
if let Some(MeteredFuture { fut, .. }) = self.engine_future.as_ref() {
match fut {
EngineFuture::ChainImport(WithBlockNumber { number, .. })
if number > &l2_head_block_info.number =>
EngineFuture::ChainImport(WithL2BlockNumber { l2_block, .. })
if l2_block > &l2_head_block_info.number =>
{
self.engine_future = None
}
Expand All @@ -182,15 +183,15 @@ where
if matches!(
self.engine_future.as_ref(),
Some(MeteredFuture {
fut: EngineFuture::L1Consolidation(WithBlockNumber { number, .. }),
fut: EngineFuture::L1Consolidation(WithL1FinalizedBlockNumber { l1_block, .. }),
..
}) if number > &l1_block_number
}) if l1_block > &l1_block_number
) {
self.engine_future = None;
}

// retain the L1 payload attributes with block number <= L1 block.
self.l1_payload_attributes.retain(|attribute| attribute.number <= l1_block_number);
self.l1_payload_attributes.retain(|attribute| attribute.l1_block <= l1_block_number);
}

/// Handles a block import request by adding it to the queue and waking up the driver.
Expand All @@ -217,10 +218,7 @@ where

/// Handles a [`ScrollPayloadAttributes`] sourced from L1 by initiating a task sending the
/// attribute to the EN via the [`EngineDriver`].
pub fn handle_l1_consolidation(
&mut self,
attributes: WithBlockNumber<ScrollPayloadAttributesWithBatchInfo>,
) {
pub fn handle_l1_consolidation(&mut self, attributes: WithFullL2Meta<ScrollPayloadAttributes>) {
self.l1_payload_attributes.push_back(attributes);
self.waker.wake();
}
Expand Down
4 changes: 2 additions & 2 deletions crates/engine/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use alloy_rpc_types_engine::PayloadError;
use rollup_node_primitives::{ScrollPayloadAttributesWithBatchInfo, WithBlockNumber};
use rollup_node_primitives::WithFullL2Meta;
use scroll_alloy_provider::ScrollEngineApiError;
use scroll_alloy_rpc_types_engine::ScrollPayloadAttributes;

Expand All @@ -21,7 +21,7 @@ pub enum EngineDriverError {
/// The payload id field is missing in the forkchoice update response for an L1 consolidation
/// job.
#[error("Forkchoice update response missing payload id for L1 consolidation job")]
L1ConsolidationMissingPayloadId(WithBlockNumber<ScrollPayloadAttributesWithBatchInfo>),
L1ConsolidationMissingPayloadId(WithFullL2Meta<ScrollPayloadAttributes>),
/// The payload id field is missing in the forkchoice update response for a payload building
/// job.
#[error("Forkchoice update response missing payload id for payload building job")]
Expand Down
25 changes: 14 additions & 11 deletions crates/engine/src/future/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use eyre::Result;
use reth_scroll_engine_primitives::try_into_block;
use reth_scroll_primitives::ScrollBlock;
use rollup_node_primitives::{
BatchInfo, BlockInfo, ChainImport, L2BlockInfoWithL1Messages, MeteredFuture,
ScrollPayloadAttributesWithBatchInfo, WithBlockNumber,
BatchInfo, BlockInfo, ChainImport, L2BlockInfoWithL1Messages, MeteredFuture, WithFullL2Meta,
WithL1FinalizedBlockNumber, WithL2BlockNumber,
};
use rollup_node_signer::SignatureAsBytes;
use scroll_alloy_hardforks::ScrollHardforks;
Expand Down Expand Up @@ -99,8 +99,8 @@ pub(crate) type OptimisticSyncFuture =
/// An enum that represents the different types of futures that can be executed on the engine API.
/// It can be a block import job, an L1 consolidation job, or a new payload processing.
pub(crate) enum EngineFuture {
ChainImport(WithBlockNumber<ChainImportFuture>),
L1Consolidation(WithBlockNumber<L1ConsolidationFuture>),
ChainImport(WithL2BlockNumber<ChainImportFuture>),
L1Consolidation(WithL1FinalizedBlockNumber<L1ConsolidationFuture>),
NewPayload(NewPayloadFuture),
OptimisticSync(OptimisticSyncFuture),
}
Expand All @@ -115,7 +115,7 @@ impl EngineFuture {
EC: ScrollEngineApi + Unpin + Send + Sync + 'static,
{
let highest_block_number = chain_import.chain.last().unwrap().number;
Self::ChainImport(WithBlockNumber::new(
Self::ChainImport(WithL2BlockNumber::new(
highest_block_number,
Box::pin(handle_chain_import(client, chain_import, fcs)),
))
Expand All @@ -133,14 +133,14 @@ impl EngineFuture {
client: Arc<EC>,
execution_payload_provider: P,
fcs: ForkchoiceState,
payload_attributes: WithBlockNumber<ScrollPayloadAttributesWithBatchInfo>,
payload_attributes: WithFullL2Meta<ScrollPayloadAttributes>,
) -> Self
where
EC: ScrollEngineApi + Unpin + Send + Sync + 'static,
P: Provider<Scroll> + Unpin + Send + Sync + 'static,
{
Self::L1Consolidation(WithBlockNumber::new(
payload_attributes.number,
Self::L1Consolidation(WithL1FinalizedBlockNumber::new(
payload_attributes.l1_block,
Box::pin(handle_payload_attributes(
client,
execution_payload_provider,
Expand Down Expand Up @@ -267,16 +267,19 @@ async fn handle_payload_attributes<EC, P>(
client: Arc<EC>,
provider: P,
fcs: ForkchoiceState,
payload_attributes_with_batch_info: WithBlockNumber<ScrollPayloadAttributesWithBatchInfo>,
payload_attributes_with_batch_info: WithFullL2Meta<ScrollPayloadAttributes>,
) -> Result<ConsolidationOutcome, EngineDriverError>
where
EC: ScrollEngineApi + Unpin + Send + Sync + 'static,
P: Provider<Scroll> + Unpin + Send + Sync + 'static,
{
tracing::trace!(target: "scroll::engine::future", ?fcs, ?payload_attributes_with_batch_info, "handling payload attributes");

let ScrollPayloadAttributesWithBatchInfo { mut payload_attributes, batch_info } =
payload_attributes_with_batch_info.inner.clone();
let batch_info = BatchInfo::new(
payload_attributes_with_batch_info.index,
payload_attributes_with_batch_info.hash,
);
let mut payload_attributes = payload_attributes_with_batch_info.inner.inner.inner.clone();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is getting unwieldy with the requirement of .inner.inner.inner. Should we consider refactoring the base types to include the additional metadata?


let maybe_execution_payload = provider
.get_block((fcs.safe_block_info().number + 1).into())
Expand Down
18 changes: 0 additions & 18 deletions crates/primitives/src/attributes.rs

This file was deleted.

76 changes: 41 additions & 35 deletions crates/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use core::{
pin::Pin,
task::{ready, Context, Poll},
};
use derive_more::{Deref, DerefMut};
use reth_primitives_traits::transaction::signed::SignedTransaction;
use reth_scroll_primitives::{ScrollBlock, ScrollTransactionSigned};
use scroll_alloy_consensus::L1_MESSAGE_TRANSACTION_TYPE;
Expand Down Expand Up @@ -83,69 +84,74 @@ impl arbitrary::Arbitrary<'_> for BlockInfo {
}
}

/// A type alias for a wrapper around a type to which a L1 finalized block number is attached.
pub type WithFinalizedBlockNumber<T> = WithBlockNumber<T>;

/// A wrapper around a type to which a block number is attached.
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub struct WithBlockNumber<T> {
/// The block number.
pub number: u64,
/// A wrapper around a type to which a L2 block number is attached.
#[derive(Debug, Deref, DerefMut, Default, Copy, Clone, PartialEq, Eq)]
pub struct WithL2BlockNumber<T> {
/// The L2 block number.
pub l2_block: u64,
/// The wrapped type.
#[deref]
#[deref_mut]
pub inner: T,
}

impl<T> WithBlockNumber<T> {
/// Returns a new instance of a [`WithBlockNumber`] wrapper.
pub const fn new(number: u64, inner: T) -> Self {
Self { number, inner }
impl<T> WithL2BlockNumber<T> {
/// Returns a new instance of a [`WithL2BlockNumber`] wrapper.
pub const fn new(l2_block: u64, inner: T) -> Self {
Self { l2_block, inner }
}
}

impl<T: Future + Unpin> Future for WithBlockNumber<T> {
type Output = WithBlockNumber<<T as Future>::Output>;
impl<T: Future + Unpin> Future for WithL2BlockNumber<T> {
type Output = WithL2BlockNumber<<T as Future>::Output>;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let block_number = self.number;
let block_number = self.l2_block;
let inner = ready!(Pin::new(&mut self.get_mut().inner).poll(cx));
Poll::Ready(WithBlockNumber::new(block_number, inner))
Poll::Ready(WithL2BlockNumber::new(block_number, inner))
}
}

/// A type alias for a wrapper around a type to which a finalized batch information is attached.
pub type WithFinalizedBatchInfo<T> = WithBatchInfo<T>;
/// A wrapper around a type to which a L1 block number is attached.
#[derive(Debug, Deref, DerefMut, Default, Copy, Clone, PartialEq, Eq)]
pub struct WithL1FinalizedBlockNumber<T> {
/// The block number.
pub l1_block: u64,
/// The wrapped type.
#[deref]
#[deref_mut]
pub inner: T,
}

/// A type alias for a wrapper around a type to which a committed batch information is attached.
pub type WithCommittedBatchInfo<T> = WithBatchInfo<T>;
impl<T> WithL1FinalizedBlockNumber<T> {
/// Returns a new instance of a [`WithL1FinalizedBlockNumber`] wrapper.
pub const fn new(l1_block: u64, inner: T) -> Self {
Self { l1_block, inner }
}
}

/// A wrapper around a type to which a batch information is attached.
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Deref, DerefMut, Default, Copy, Clone, PartialEq, Eq)]
pub struct WithBatchInfo<T> {
/// The l1 block number associated with the batch.
pub number: u64,
/// The index of the batch.
pub index: u64,
/// The hash of the batch.
pub hash: B256,
/// The wrapped type.
#[deref]
#[deref_mut]
pub inner: T,
}

impl<T> WithBatchInfo<T> {
/// Returns a new instance of a [`WithBatchInfo`] wrapper.
pub const fn new(index: u64, number: u64, inner: T) -> Self {
Self { index, number, inner }
pub const fn new(index: u64, hash: B256, inner: T) -> Self {
Self { index, hash, inner }
}
}

impl<T: Future + Unpin> Future for WithBatchInfo<T> {
type Output = WithBatchInfo<<T as Future>::Output>;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let block_number = self.number;
let index = self.index;
let inner = ready!(Pin::new(&mut self.get_mut().inner).poll(cx));
Poll::Ready(WithBatchInfo::new(index, block_number, inner))
}
}
/// Type alias for a wrapper type with the full L2 metadata.
pub type WithFullL2Meta<T> = WithL1FinalizedBlockNumber<WithL2BlockNumber<WithBatchInfo<T>>>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above, this is a complex type. Should we push the additional metadata into the inner type T.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can do, I like the idea of having these composable wrappers, so we can just quickly attach some extra information to structures. But I can push this info to the T


/// This struct represents an L2 block with a vector the hashes of the L1 messages included in the
/// block.
Expand Down
7 changes: 2 additions & 5 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
#[cfg(not(feature = "std"))]
extern crate alloc as std;

mod attributes;
pub use attributes::ScrollPayloadAttributesWithBatchInfo;

mod block;
pub use block::{
BlockInfo, L2BlockInfoWithL1Messages, WithBatchInfo, WithBlockNumber, WithCommittedBatchInfo,
WithFinalizedBatchInfo, WithFinalizedBlockNumber, DEFAULT_BLOCK_DIFFICULTY,
BlockInfo, L2BlockInfoWithL1Messages, WithBatchInfo, WithFullL2Meta,
WithL1FinalizedBlockNumber, WithL2BlockNumber, DEFAULT_BLOCK_DIFFICULTY,
};

mod batch;
Expand Down