Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(derive): L2ChainProvider w/ op-alloy-consensus #98

Merged
merged 3 commits into from
Apr 14, 2024
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
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ tracing-subscriber = "0.3.18"

[features]
default = ["serde", "k256"]
serde = ["dep:serde", "alloy-primitives/serde"]
k256 = ["alloy-primitives/k256", "alloy-consensus/k256"]
serde = ["dep:serde", "alloy-primitives/serde", "alloy-consensus/serde", "op-alloy-consensus/serde"]
k256 = ["alloy-primitives/k256", "alloy-consensus/k256", "op-alloy-consensus/k256"]
online = [
"dep:alloy-provider",
"dep:alloy-transport-http",
Expand Down
20 changes: 10 additions & 10 deletions crates/derive/src/alloy_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use crate::{
traits::{ChainProvider, L2ChainProvider},
types::{Block, BlockInfo, ExecutionPayloadEnvelope, L2BlockInfo, RollupConfig},
types::{Block, BlockInfo, L2BlockInfo, L2ExecutionPayloadEnvelope, OpBlock, RollupConfig},
};
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use alloy_consensus::{Header, Receipt, ReceiptWithBloom, TxEnvelope, TxType};
Expand Down Expand Up @@ -149,26 +149,26 @@ impl<T: Provider<Http<reqwest::Client>>> ChainProvider for AlloyChainProvider<T>
}
}

/// The [AlloyL2SafeHeadProvider] is a concrete implementation of the [L2ChainProvider] trait,
/// The [AlloyL2ChainProvider] is a concrete implementation of the [L2ChainProvider] trait,
/// providing data over Ethereum JSON-RPC using an alloy provider as the backend.
///
/// **Note**:
/// This provider fetches data using the `debug_getRawBlock` method. The RPC must support this
/// namespace.
#[derive(Debug)]
pub struct AlloyL2SafeHeadProvider<T: Provider<Http<reqwest::Client>>> {
pub struct AlloyL2ChainProvider<T: Provider<Http<reqwest::Client>>> {
/// The inner Ethereum JSON-RPC provider.
inner: T,
/// The rollup configuration.
rollup_config: Arc<RollupConfig>,
/// `payload_by_number` LRU cache.
payload_by_number_cache: LruCache<u64, ExecutionPayloadEnvelope>,
payload_by_number_cache: LruCache<u64, L2ExecutionPayloadEnvelope>,
/// `l2_block_info_by_number` LRU cache.
l2_block_info_by_number_cache: LruCache<u64, L2BlockInfo>,
}

impl<T: Provider<Http<reqwest::Client>>> AlloyL2SafeHeadProvider<T> {
/// Creates a new [AlloyL2SafeHeadProvider] with the given alloy provider and [RollupConfig].
impl<T: Provider<Http<reqwest::Client>>> AlloyL2ChainProvider<T> {
/// Creates a new [AlloyL2ChainProvider] with the given alloy provider and [RollupConfig].
pub fn new(inner: T, rollup_config: Arc<RollupConfig>) -> Self {
Self {
inner,
Expand All @@ -180,7 +180,7 @@ impl<T: Provider<Http<reqwest::Client>>> AlloyL2SafeHeadProvider<T> {
}

#[async_trait]
impl<T: Provider<Http<reqwest::Client>>> L2ChainProvider for AlloyL2SafeHeadProvider<T> {
impl<T: Provider<Http<reqwest::Client>>> L2ChainProvider for AlloyL2ChainProvider<T> {
async fn l2_block_info_by_number(&mut self, number: u64) -> Result<L2BlockInfo> {
if let Some(l2_block_info) = self.l2_block_info_by_number_cache.get(&number) {
return Ok(*l2_block_info);
Expand All @@ -192,7 +192,7 @@ impl<T: Provider<Http<reqwest::Client>>> L2ChainProvider for AlloyL2SafeHeadProv
Ok(l2_block_info)
}

async fn payload_by_number(&mut self, number: u64) -> Result<ExecutionPayloadEnvelope> {
async fn payload_by_number(&mut self, number: u64) -> Result<L2ExecutionPayloadEnvelope> {
if let Some(payload) = self.payload_by_number_cache.get(&number) {
return Ok(payload.clone());
}
Expand All @@ -203,8 +203,8 @@ impl<T: Provider<Http<reqwest::Client>>> L2ChainProvider for AlloyL2SafeHeadProv
.request("debug_getRawBlock", [U64::from(number)])
.await
.map_err(|e| anyhow!(e))?;
let block = Block::decode(&mut raw_block.as_ref()).map_err(|e| anyhow!(e))?;
let payload_envelope: ExecutionPayloadEnvelope = block.into();
let block = OpBlock::decode(&mut raw_block.as_ref()).map_err(|e| anyhow!(e))?;
let payload_envelope: L2ExecutionPayloadEnvelope = block.into();

self.payload_by_number_cache.put(number, payload_envelope.clone());
Ok(payload_envelope)
Expand Down
22 changes: 11 additions & 11 deletions crates/derive/src/stages/attributes_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use crate::{
traits::{OriginProvider, ResettableStage},
types::{
AttributesWithParent, BlockInfo, L2BlockInfo, PayloadAttributes, ResetError, RollupConfig,
SingleBatch, StageError, StageResult, SystemConfig,
BlockInfo, L2AttributesWithParent, L2BlockInfo, L2PayloadAttributes, ResetError,
RollupConfig, SingleBatch, StageError, StageResult, SystemConfig,
},
};
use alloc::boxed::Box;
Expand All @@ -29,7 +29,7 @@ pub trait AttributesProvider {
}

/// [AttributesQueue] accepts batches from the [BatchQueue] stage
/// and transforms them into [PayloadAttributes]. The outputted payload
/// and transforms them into [L2PayloadAttributes]. The outputted payload
/// attributes cannot be buffered because each batch->attributes transformation
/// pulls in data about the current L2 safe head.
///
Expand Down Expand Up @@ -80,28 +80,28 @@ where
pub async fn next_attributes(
&mut self,
parent: L2BlockInfo,
) -> StageResult<AttributesWithParent> {
) -> StageResult<L2AttributesWithParent> {
// Load the batch.
let batch = self.load_batch(parent).await?;

// Construct the payload attributes from the loaded batch.
let attributes = self.create_next_attributes(batch, parent).await?;
let populated_attributes =
AttributesWithParent { attributes, parent, is_last_in_span: self.is_last_in_span };
L2AttributesWithParent { attributes, parent, is_last_in_span: self.is_last_in_span };

// Clear out the local state once payload attributes are prepared.
self.batch = None;
self.is_last_in_span = false;
Ok(populated_attributes)
}

/// Creates the next attributes, transforming a [SingleBatch] into [PayloadAttributes].
/// Creates the next attributes, transforming a [SingleBatch] into [L2PayloadAttributes].
/// This sets `no_tx_pool` and appends the batched txs to the attributes tx list.
pub async fn create_next_attributes(
&mut self,
batch: SingleBatch,
parent: L2BlockInfo,
) -> StageResult<PayloadAttributes> {
) -> StageResult<L2PayloadAttributes> {
// Sanity check parent hash
if batch.parent_hash != parent.block_info.hash {
return Err(StageError::Reset(ResetError::BadParentHash(
Expand Down Expand Up @@ -164,7 +164,7 @@ where
#[cfg(test)]
mod tests {
use super::{
AttributesQueue, AttributesWithParent, BlockInfo, L2BlockInfo, PayloadAttributes,
AttributesQueue, BlockInfo, L2AttributesWithParent, L2BlockInfo, L2PayloadAttributes,
RollupConfig, SingleBatch, StageError, StageResult,
};
use crate::{
Expand Down Expand Up @@ -272,7 +272,7 @@ mod tests {
async fn test_create_next_attributes_success() {
let cfg = RollupConfig::default();
let mock = new_attributes_provider(None, vec![]);
let mut payload_attributes = PayloadAttributes::default();
let mut payload_attributes = L2PayloadAttributes::default();
let mock_builder =
MockAttributesBuilder { attributes: vec![Ok(payload_attributes.clone())] };
let mut aq = AttributesQueue::new(cfg, mock, mock_builder);
Expand All @@ -298,7 +298,7 @@ mod tests {
async fn test_next_attributes_load_batch_last_in_span() {
let cfg = RollupConfig::default();
let mock = new_attributes_provider(None, vec![Ok(Default::default())]);
let mut pa = PayloadAttributes::default();
let mut pa = L2PayloadAttributes::default();
let mock_builder = MockAttributesBuilder { attributes: vec![Ok(pa.clone())] };
let mut aq = AttributesQueue::new(cfg, mock, mock_builder);
// If we load the batch, we should get the last in span.
Expand All @@ -310,7 +310,7 @@ mod tests {
// It should also reset the last in span flag and clear the batch.
let attributes = aq.next_attributes(L2BlockInfo::default()).await.unwrap();
pa.no_tx_pool = true;
let populated_attributes = AttributesWithParent {
let populated_attributes = L2AttributesWithParent {
attributes: pa,
parent: L2BlockInfo::default(),
is_last_in_span: true,
Expand Down
12 changes: 6 additions & 6 deletions crates/derive/src/stages/attributes_queue/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
params::SEQUENCER_FEE_VAULT_ADDRESS,
traits::ChainProvider,
types::{
BlockID, BuilderError, EcotoneTransactionBuilder, L2BlockInfo, PayloadAttributes,
BlockID, BuilderError, EcotoneTransactionBuilder, L2BlockInfo, L2PayloadAttributes,
RawTransaction, RollupConfig, SystemConfig,
},
};
Expand All @@ -17,18 +17,18 @@ use async_trait::async_trait;
/// that can be used to construct an L2 Block containing only deposits.
#[async_trait]
pub trait AttributesBuilder {
/// Prepares a template [PayloadAttributes] that is ready to be used to build an L2 block.
/// Prepares a template [L2PayloadAttributes] that is ready to be used to build an L2 block.
/// The block will contain deposits only, on top of the given L2 parent, with the L1 origin
/// set to the given epoch.
/// By default, the [PayloadAttributes] template will have `no_tx_pool` set to true,
/// By default, the [L2PayloadAttributes] template will have `no_tx_pool` set to true,
/// and no sequencer transactions. The caller has to modify the template to add transactions.
/// This can be done by either setting the `no_tx_pool` to false as sequencer, or by appending
/// batch transactions as the verifier.
async fn prepare_payload_attributes(
&mut self,
l2_parent: L2BlockInfo,
epoch: BlockID,
) -> Result<PayloadAttributes, BuilderError>;
) -> Result<L2PayloadAttributes, BuilderError>;
}

/// The [SystemConfigL2Fetcher] fetches the system config by L2 hash.
Expand Down Expand Up @@ -73,7 +73,7 @@ where
&mut self,
l2_parent: L2BlockInfo,
epoch: BlockID,
) -> Result<PayloadAttributes, BuilderError> {
) -> Result<L2PayloadAttributes, BuilderError> {
let l1_header;
let deposit_transactions: Vec<RawTransaction>;
// let mut sequence_number = 0u64;
Expand Down Expand Up @@ -151,7 +151,7 @@ where
parent_beacon_root = Some(l1_header.parent_beacon_block_root.unwrap_or_default());
}

Ok(PayloadAttributes {
Ok(L2PayloadAttributes {
timestamp: next_l2_time,
prev_randao: l1_header.mix_hash,
fee_recipient: SEQUENCER_FEE_VAULT_ADDRESS,
Expand Down
8 changes: 4 additions & 4 deletions crates/derive/src/stages/test_utils/attributes_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::{
stages::attributes_queue::{AttributesBuilder, AttributesProvider},
traits::OriginProvider,
types::{
BlockID, BlockInfo, BuilderError, L2BlockInfo, PayloadAttributes, SingleBatch, StageError,
StageResult,
BlockID, BlockInfo, BuilderError, L2BlockInfo, L2PayloadAttributes, SingleBatch,
StageError, StageResult,
},
};
use alloc::{boxed::Box, vec::Vec};
Expand All @@ -15,7 +15,7 @@ use async_trait::async_trait;
#[derive(Debug, Default)]
pub struct MockAttributesBuilder {
/// The attributes to return.
pub attributes: Vec<anyhow::Result<PayloadAttributes>>,
pub attributes: Vec<anyhow::Result<L2PayloadAttributes>>,
}

#[async_trait]
Expand All @@ -25,7 +25,7 @@ impl AttributesBuilder for MockAttributesBuilder {
&mut self,
_l2_parent: L2BlockInfo,
_epoch: BlockID,
) -> Result<PayloadAttributes, BuilderError> {
) -> Result<L2PayloadAttributes, BuilderError> {
match self.attributes.pop() {
Some(Ok(attrs)) => Ok(attrs),
Some(Err(err)) => Err(BuilderError::Custom(err)),
Expand Down
4 changes: 2 additions & 2 deletions crates/derive/src/traits/data_sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! pipeline's stages.

use crate::types::{
Blob, BlockInfo, ExecutionPayloadEnvelope, IndexedBlobHash, L2BlockInfo, StageResult,
Blob, BlockInfo, IndexedBlobHash, L2BlockInfo, L2ExecutionPayloadEnvelope, StageResult,
};
use alloc::{boxed::Box, fmt::Debug, vec::Vec};
use alloy_consensus::{Header, Receipt, TxEnvelope};
Expand Down Expand Up @@ -40,7 +40,7 @@ pub trait L2ChainProvider {

/// Returns an execution payload for a given number.
/// Errors if the execution payload does not exist.
async fn payload_by_number(&mut self, number: u64) -> Result<ExecutionPayloadEnvelope>;
async fn payload_by_number(&mut self, number: u64) -> Result<L2ExecutionPayloadEnvelope>;
}

/// The BlobProvider trait specifies the functionality of a data source that can provide blobs.
Expand Down
8 changes: 4 additions & 4 deletions crates/derive/src/traits/test_utils/data_sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
traits::{ChainProvider, L2ChainProvider},
types::{BlockInfo, ExecutionPayloadEnvelope, L2BlockInfo},
types::{BlockInfo, L2BlockInfo, L2ExecutionPayloadEnvelope},
};
use alloc::{boxed::Box, vec::Vec};
use alloy_consensus::{Header, Receipt, TxEnvelope};
Expand All @@ -16,12 +16,12 @@ pub struct MockBlockFetcher {
/// Blocks
pub blocks: Vec<L2BlockInfo>,
/// Payloads
pub payloads: Vec<ExecutionPayloadEnvelope>,
pub payloads: Vec<L2ExecutionPayloadEnvelope>,
}

impl MockBlockFetcher {
/// Creates a new [MockBlockFetcher] with the given origin and batches.
pub fn new(blocks: Vec<L2BlockInfo>, payloads: Vec<ExecutionPayloadEnvelope>) -> Self {
pub fn new(blocks: Vec<L2BlockInfo>, payloads: Vec<L2ExecutionPayloadEnvelope>) -> Self {
Self { blocks, payloads }
}
}
Expand All @@ -36,7 +36,7 @@ impl L2ChainProvider for MockBlockFetcher {
.ok_or_else(|| anyhow::anyhow!("Block not found"))
}

async fn payload_by_number(&mut self, number: u64) -> Result<ExecutionPayloadEnvelope> {
async fn payload_by_number(&mut self, number: u64) -> Result<L2ExecutionPayloadEnvelope> {
self.payloads
.iter()
.find(|p| p.execution_payload.block_number == number)
Expand Down
16 changes: 10 additions & 6 deletions crates/derive/src/types/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use alloy_primitives::{Address, B256};
/// Payload attributes.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct PayloadAttributes {
pub struct L2PayloadAttributes {
/// Value for the timestamp field of the new payload.
#[cfg_attr(feature = "serde", serde(rename = "timestamp"))]
pub timestamp: u64,
Expand Down Expand Up @@ -42,23 +42,27 @@ pub struct PayloadAttributes {

/// Payload Attributes with parent block reference.
#[derive(Debug, Clone, PartialEq)]
pub struct AttributesWithParent {
pub struct L2AttributesWithParent {
/// The payload attributes.
pub attributes: PayloadAttributes,
pub attributes: L2PayloadAttributes,
/// The parent block reference.
pub parent: L2BlockInfo,
/// Whether the current batch is the last in its span.
pub is_last_in_span: bool,
}

impl AttributesWithParent {
impl L2AttributesWithParent {
/// Create a new [AttributesWithParent] instance.
pub fn new(attributes: PayloadAttributes, parent: L2BlockInfo, is_last_in_span: bool) -> Self {
pub fn new(
attributes: L2PayloadAttributes,
parent: L2BlockInfo,
is_last_in_span: bool,
) -> Self {
Self { attributes, parent, is_last_in_span }
}

/// Returns the payload attributes.
pub fn attributes(&self) -> &PayloadAttributes {
pub fn attributes(&self) -> &L2PayloadAttributes {
&self.attributes
}

Expand Down
Loading
Loading