diff --git a/Cargo.lock b/Cargo.lock index 088746a791..6c1a623346 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1847,6 +1847,7 @@ dependencies = [ "op-alloy-consensus", "serde", "serde_json", + "superchain-primitives", ] [[package]] @@ -2844,6 +2845,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3013,6 +3025,22 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "superchain-primitives" +version = "0.1.0" +source = "git+https://github.com/ethereum-optimism/superchain-registry?branch=main#1f424d06db64eebfd265c0a411554843f5522222" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-sol-types", + "anyhow", + "hashbrown", + "serde", + "serde_repr", +] + [[package]] name = "syn" version = "1.0.109" diff --git a/bin/programs/client/src/l2/executor/mod.rs b/bin/programs/client/src/l2/executor/mod.rs index 56a0f2a0a3..572d020157 100644 --- a/bin/programs/client/src/l2/executor/mod.rs +++ b/bin/programs/client/src/l2/executor/mod.rs @@ -418,9 +418,15 @@ where .next_block_excess_blob_gas() .or_else(|| spec_id.is_enabled_in(SpecId::ECOTONE).then_some(0)) .map(|x| BlobExcessGasAndPrice::new(x as u64)); - let next_block_base_fee = parent_header - .next_block_base_fee(config.base_fee_params_at_timestamp(payload_attrs.timestamp)) - .unwrap_or_default(); + // If the payload attribute timestamp is past canyon activation, + // use the canyon base fee params from the rollup config. + let base_fee_params = if config.is_canyon_active(payload_attrs.timestamp) { + config.canyon_base_fee_params.unwrap_or(config.base_fee_params) + } else { + config.base_fee_params + }; + let next_block_base_fee = + parent_header.next_block_base_fee(base_fee_params).unwrap_or_default(); BlockEnv { number: U256::from(parent_header.number + 1), @@ -581,6 +587,7 @@ mod test { use super::*; use alloy_primitives::{address, b256, hex}; use alloy_rlp::Decodable; + use kona_derive::types::{OP_BASE_FEE_PARAMS, OP_CANYON_BASE_FEE_PARAMS}; use kona_mpt::NoopTrieDBHinter; use serde::Deserialize; use std::{collections::HashMap, format}; @@ -640,6 +647,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), + base_fee_params: OP_BASE_FEE_PARAMS, + canyon_base_fee_params: Some(OP_CANYON_BASE_FEE_PARAMS), ..Default::default() }; @@ -691,6 +700,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), + base_fee_params: OP_BASE_FEE_PARAMS, + canyon_base_fee_params: Some(OP_CANYON_BASE_FEE_PARAMS), ..Default::default() }; @@ -746,6 +757,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), + base_fee_params: OP_BASE_FEE_PARAMS, + canyon_base_fee_params: Some(OP_CANYON_BASE_FEE_PARAMS), ..Default::default() }; @@ -808,6 +821,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), + base_fee_params: OP_BASE_FEE_PARAMS, + canyon_base_fee_params: Some(OP_CANYON_BASE_FEE_PARAMS), ..Default::default() }; @@ -864,6 +879,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), + base_fee_params: OP_BASE_FEE_PARAMS, + canyon_base_fee_params: Some(OP_CANYON_BASE_FEE_PARAMS), ..Default::default() }; @@ -929,6 +946,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), + base_fee_params: OP_BASE_FEE_PARAMS, + canyon_base_fee_params: Some(OP_CANYON_BASE_FEE_PARAMS), ..Default::default() }; diff --git a/bin/sync/src/main.rs b/bin/sync/src/main.rs index a9b4cfa8ae..c6228889ea 100644 --- a/bin/sync/src/main.rs +++ b/bin/sync/src/main.rs @@ -1,10 +1,6 @@ -use alloy_primitives::{address, b256, U256}; use anyhow::{anyhow, Result}; use clap::Parser; -use kona_derive::{ - online::*, - types::{BlockID, Genesis, RollupConfig, SystemConfig}, -}; +use kona_derive::{online::*, types::OP_MAINNET_CONFIG}; use reqwest::Url; use std::sync::Arc; use tracing::{debug, error, info, warn, Level}; @@ -20,11 +16,7 @@ const BEACON_URL: &str = "BEACON_URL"; async fn main() -> Result<()> { let cfg = crate::cli::Cli::parse(); init_tracing_subscriber(cfg.v)?; - info!(target: "sync", "Initialized telemetry"); - - sync(cfg).await?; - - Ok(()) + sync(cfg).await } async fn sync(cli_cfg: crate::cli::Cli) -> Result<()> { @@ -43,9 +35,9 @@ async fn sync(cli_cfg: crate::cli::Cli) -> Result<()> { cli_cfg.beacon_url.unwrap_or_else(|| std::env::var(BEACON_URL).unwrap()); // Construct the pipeline and payload validator. - let cfg = Arc::new(new_op_mainnet_config()); + let cfg = Arc::new(OP_MAINNET_CONFIG); let start = cli_cfg.start_l2_block.unwrap_or(cfg.genesis.l2.number); - let l1_provider = AlloyChainProvider::new_http(l1_rpc_url); + let mut l1_provider = AlloyChainProvider::new_http(l1_rpc_url); let mut l2_provider = AlloyL2ChainProvider::new_http(l2_rpc_url.clone(), cfg.clone()); let attributes = StatefulAttributesBuilder::new(cfg.clone(), l2_provider.clone(), l1_provider.clone()); @@ -53,33 +45,47 @@ async fn sync(cli_cfg: crate::cli::Cli) -> Result<()> { let blob_provider = OnlineBlobProvider::<_, SimpleSlotDerivation>::new(beacon_client, None, None); let dap = EthereumDataSource::new(l1_provider.clone(), blob_provider, &cfg); + let mut cursor = l2_provider + .l2_block_info_by_number(start) + .await + .expect("Failed to fetch genesis L2 block info for pipeline cursor"); + let tip = l1_provider + .block_info_by_number(cursor.l1_origin.number) + .await + .expect("Failed to fetch genesis L1 block info for pipeline tip"); let mut pipeline = - new_online_pipeline(cfg, l1_provider, dap, l2_provider.clone(), attributes, start).await; + new_online_pipeline(cfg, l1_provider, dap, l2_provider.clone(), attributes, tip).await; let validator = OnlineValidator::new_http(l2_rpc_url); let mut derived_attributes_count = 0; // Continuously step on the pipeline and validate payloads. loop { info!(target: "loop", "Validated payload attributes number {}", derived_attributes_count); - info!(target: "loop", "Pending l2 safe head num: {}", pipeline.cursor.block_info.number); - match pipeline.step().await { + info!(target: "loop", "Pending l2 safe head num: {}", cursor.block_info.number); + match pipeline.step(cursor).await { Ok(_) => info!(target: "loop", "Stepped derivation pipeline"), Err(e) => warn!(target: "loop", "Error stepping derivation pipeline: {:?}", e), } - if let Some(attributes) = pipeline.pop() { + if let Some(attributes) = pipeline.next_attributes() { if !validator.validate(&attributes).await { error!(target: "loop", "Failed payload validation: {}", attributes.parent.block_info.hash); - continue; + return Ok(()); } derived_attributes_count += 1; - match l2_provider.l2_block_info_by_number(pipeline.cursor.block_info.number + 1).await { - Ok(bi) => pipeline.update_cursor(bi), + match l2_provider.l2_block_info_by_number(cursor.block_info.number + 1).await { + Ok(bi) => cursor = bi, Err(e) => { - error!(target: "loop", "Failed to fetch next pending l2 safe head: {}, err: {:?}", pipeline.cursor.block_info.number + 1, e); + error!(target: "loop", "Failed to fetch next pending l2 safe head: {}, err: {:?}", cursor.block_info.number + 1, e); } } - dbg!(attributes); + println!( + "Validated Payload Attributes {derived_attributes_count} [L2 Block Num: {}] [L2 Timestamp: {}] [L1 Origin Block Num: {}]", + attributes.parent.block_info.number + 1, + attributes.attributes.timestamp, + pipeline.origin().unwrap().number, + ); + info!(target: "loop", "attributes: {:#?}", attributes); } else { debug!(target: "loop", "No attributes to validate"); } @@ -98,43 +104,3 @@ fn init_tracing_subscriber(v: u8) -> Result<()> { .finish(); tracing::subscriber::set_global_default(subscriber).map_err(|e| anyhow!(e)) } - -fn new_op_mainnet_config() -> RollupConfig { - RollupConfig { - genesis: Genesis { - l1: BlockID { - hash: b256!("438335a20d98863a4c0c97999eb2481921ccd28553eac6f913af7c12aec04108"), - number: 17_422_590_u64, - }, - l2: BlockID { - hash: b256!("dbf6a80fef073de06add9b0d14026d6e5a86c85f6d102c36d3d8e9cf89c2afd3"), - number: 105_235_063_u64, - }, - timestamp: 1_686_068_903_u64, - system_config: SystemConfig { - batcher_addr: address!("6887246668a3b87f54deb3b94ba47a6f63f32985"), - l1_fee_overhead: U256::from(0xbc), - l1_fee_scalar: U256::from(0xa6fe0), - gas_limit: U256::from(30_000_000_u64), - }, - }, - block_time: 2_u64, - max_sequencer_drift: 600_u64, - seq_window_size: 3600_u64, - channel_timeout: 300_u64, - l1_chain_id: 1_u64, - l2_chain_id: 10_u64, - regolith_time: Some(0_u64), - canyon_time: Some(1_704_992_401_u64), - delta_time: Some(1_708_560_000_u64), - ecotone_time: Some(1_710_374_401_u64), - fjord_time: Some(1_720_627_201_u64), - interop_time: None, - batch_inbox_address: address!("ff00000000000000000000000000000000000010"), - deposit_contract_address: address!("beb5fc579115071764c7423a4f12edde41f106ed"), - l1_system_config_address: address!("229047fed2591dbec1ef1118d64f7af3db9eb290"), - protocol_versions_address: address!("8062abc286f5e7d9428a0ccb9abd71e50d93b935"), - da_challenge_address: Some(address!("0000000000000000000000000000000000000000")), - blobs_enabled_l1_timestamp: None, - } -} diff --git a/crates/derive/src/online/alloy_providers.rs b/crates/derive/src/online/alloy_providers.rs index ad497bdc94..422c7412cc 100644 --- a/crates/derive/src/online/alloy_providers.rs +++ b/crates/derive/src/online/alloy_providers.rs @@ -219,7 +219,7 @@ impl L2ChainProvider for AlloyL2ChainProvider { rollup_config: Arc, ) -> Result { if let Some(system_config) = self.system_config_by_number_cache.get(&number) { - return Ok(*system_config); + return Ok(system_config.clone()); } let envelope = self.payload_by_number(number).await?; diff --git a/crates/derive/src/online/mod.rs b/crates/derive/src/online/mod.rs index d922a08850..c90ece08f8 100644 --- a/crates/derive/src/online/mod.rs +++ b/crates/derive/src/online/mod.rs @@ -5,7 +5,7 @@ pub use crate::{ pipeline::{DerivationPipeline, PipelineBuilder}, sources::EthereumDataSource, stages::StatefulAttributesBuilder, - traits::{ChainProvider, L2ChainProvider, Pipeline}, + traits::{ChainProvider, L2ChainProvider, OriginProvider, Pipeline}, types::RollupConfig, }; diff --git a/crates/derive/src/online/pipeline.rs b/crates/derive/src/online/pipeline.rs index cf18f2f039..f141750ca9 100644 --- a/crates/derive/src/online/pipeline.rs +++ b/crates/derive/src/online/pipeline.rs @@ -11,8 +11,7 @@ use crate::{ AttributesQueue, BatchQueue, ChannelBank, ChannelReader, FrameQueue, L1Retrieval, L1Traversal, StatefulAttributesBuilder, }, - traits::{ChainProvider, L2ChainProvider}, - types::RollupConfig, + types::{BlockInfo, RollupConfig}, }; use alloc::sync::Arc; @@ -44,27 +43,18 @@ pub type OnlineAttributesQueue = AttributesQueue< /// Internally, this uses the [PipelineBuilder] to construct the pipeline. pub async fn new_online_pipeline( rollup_config: Arc, - mut chain_provider: AlloyChainProvider, + chain_provider: AlloyChainProvider, dap_source: OnlineDataProvider, - mut l2_chain_provider: AlloyL2ChainProvider, + l2_chain_provider: AlloyL2ChainProvider, builder: OnlineAttributesBuilder, - start_block: u64, + origin: BlockInfo, ) -> OnlinePipeline { - let cursor = l2_chain_provider - .l2_block_info_by_number(start_block) - .await - .expect("Failed to fetch genesis L2 block info for pipeline cursor"); - let tip = chain_provider - .block_info_by_number(cursor.l1_origin.number) - .await - .expect("Failed to fetch genesis L1 block info for pipeline tip"); PipelineBuilder::new() .rollup_config(rollup_config) .dap_source(dap_source) .l2_chain_provider(l2_chain_provider) .chain_provider(chain_provider) .builder(builder) - .start_cursor(cursor) - .tip(tip) + .origin(origin) .build() } diff --git a/crates/derive/src/pipeline/builder.rs b/crates/derive/src/pipeline/builder.rs index 9f21091a26..ae4b137e42 100644 --- a/crates/derive/src/pipeline/builder.rs +++ b/crates/derive/src/pipeline/builder.rs @@ -6,9 +6,9 @@ use super::{ use crate::stages::{ AttributesQueue, BatchQueue, ChannelBank, ChannelReader, FrameQueue, L1Retrieval, L1Traversal, }; -use alloc::{collections::VecDeque, sync::Arc}; +use alloc::sync::Arc; use core::fmt::Debug; -use kona_primitives::{BlockInfo, L2BlockInfo, RollupConfig}; +use kona_primitives::{BlockInfo, RollupConfig}; type L1TraversalStage

= L1Traversal

; type L1RetrievalStage = L1Retrieval>; @@ -32,9 +32,8 @@ where dap_source: Option, chain_provider: Option

, builder: Option, + origin: Option, rollup_config: Option>, - start_cursor: Option, - tip: Option, } impl Default for PipelineBuilder @@ -50,9 +49,8 @@ where dap_source: None, chain_provider: None, builder: None, - tip: None, + origin: None, rollup_config: None, - start_cursor: None, } } } @@ -75,15 +73,9 @@ where self } - /// Sets the tip for the pipeline. - pub fn tip(mut self, tip: BlockInfo) -> Self { - self.tip = Some(tip); - self - } - - /// Sets the start cursor for the pipeline. - pub fn start_cursor(mut self, cursor: L2BlockInfo) -> Self { - self.start_cursor = Some(cursor); + /// Sets the origin L1 block for the pipeline. + pub fn origin(mut self, origin: BlockInfo) -> Self { + self.origin = Some(origin); self } @@ -135,23 +127,17 @@ where // Compose the stage stack. let mut l1_traversal = L1Traversal::new(chain_provider, Arc::clone(&rollup_config)); - l1_traversal.block = builder.tip; + l1_traversal.block = Some(builder.origin.expect("origin must be set")); let l1_retrieval = L1Retrieval::new(l1_traversal, dap_source); let frame_queue = FrameQueue::new(l1_retrieval); let channel_bank = ChannelBank::new(Arc::clone(&rollup_config), frame_queue); let channel_reader = ChannelReader::new(channel_bank, Arc::clone(&rollup_config)); let batch_queue = BatchQueue::new(rollup_config.clone(), channel_reader, l2_chain_provider.clone()); - let attributes = AttributesQueue::new(*rollup_config, batch_queue, attributes_builder); + let attributes = + AttributesQueue::new(rollup_config.clone(), batch_queue, attributes_builder); // Create the pipeline. - DerivationPipeline { - attributes, - tip: builder.tip.unwrap_or_default(), - prepared: VecDeque::new(), - cursor: builder.start_cursor.unwrap_or_default(), - rollup_config, - l2_chain_provider, - } + DerivationPipeline::new(attributes, rollup_config, l2_chain_provider) } } diff --git a/crates/derive/src/pipeline/core.rs b/crates/derive/src/pipeline/core.rs index 1e222187cd..dc4413ece8 100644 --- a/crates/derive/src/pipeline/core.rs +++ b/crates/derive/src/pipeline/core.rs @@ -1,7 +1,8 @@ //! Contains the core derivation pipeline. use super::{ - L2ChainProvider, NextAttributes, OriginAdvancer, Pipeline, ResettableStage, StageError, + L2ChainProvider, NextAttributes, OriginAdvancer, OriginProvider, Pipeline, ResettableStage, + StageError, }; use alloc::{boxed::Box, collections::VecDeque, sync::Arc}; use async_trait::async_trait; @@ -12,7 +13,7 @@ use kona_primitives::{BlockInfo, L2AttributesWithParent, L2BlockInfo, RollupConf #[derive(Debug)] pub struct DerivationPipeline where - S: NextAttributes + ResettableStage + OriginAdvancer + Debug + Send, + S: NextAttributes + ResettableStage + OriginProvider + OriginAdvancer + Debug + Send, P: L2ChainProvider + Send + Sync + Debug, { /// A handle to the next attributes. @@ -20,10 +21,6 @@ where /// Reset provider for the pipeline. /// A list of prepared [L2AttributesWithParent] to be used by the derivation pipeline consumer. pub prepared: VecDeque, - /// A cursor for the [L2BlockInfo] parent to be used when pulling the next attributes. - pub cursor: L2BlockInfo, - /// L1 Origin Tip - pub tip: BlockInfo, /// The rollup config. pub rollup_config: Arc, /// The L2 Chain Provider used to fetch the system config on reset. @@ -32,59 +29,44 @@ where impl DerivationPipeline where - S: NextAttributes + ResettableStage + OriginAdvancer + Debug + Send, + S: NextAttributes + ResettableStage + OriginProvider + OriginAdvancer + Debug + Send, P: L2ChainProvider + Send + Sync + Debug, { /// Creates a new instance of the [DerivationPipeline]. - pub fn new( - attributes: S, - tip: BlockInfo, - cursor: L2BlockInfo, - rollup_config: Arc, - l2_chain_provider: P, - ) -> Self { - Self { - attributes, - prepared: VecDeque::new(), - rollup_config, - tip, - cursor, - l2_chain_provider, - } + pub fn new(attributes: S, rollup_config: Arc, l2_chain_provider: P) -> Self { + Self { attributes, prepared: VecDeque::new(), rollup_config, l2_chain_provider } + } +} + +impl OriginProvider for DerivationPipeline +where + S: NextAttributes + ResettableStage + OriginProvider + OriginAdvancer + Debug + Send, + P: L2ChainProvider + Send + Sync + Debug, +{ + fn origin(&self) -> Option { + self.attributes.origin() } } #[async_trait] impl Pipeline for DerivationPipeline where - S: NextAttributes + ResettableStage + OriginAdvancer + Debug + Send, + S: NextAttributes + ResettableStage + OriginProvider + OriginAdvancer + Debug + Send + Sync, P: L2ChainProvider + Send + Sync + Debug, { - /// Pops the next prepared [L2AttributesWithParent] from the pipeline. - fn pop(&mut self) -> Option { + /// Returns the next prepared [L2AttributesWithParent] from the pipeline. + fn next_attributes(&mut self) -> Option { self.prepared.pop_front() } - /// Updates the L2 Safe Head cursor of the pipeline. - /// The cursor is used to fetch the next attributes. - fn update_cursor(&mut self, cursor: L2BlockInfo) { - self.cursor = cursor; - } - - /// Sets the L1 Origin of the pipeline. - fn set_origin(&mut self, origin: BlockInfo) { - self.tip = origin; - } - /// Resets the pipelien by calling the [`ResettableStage::reset`] method. /// This will bubble down the stages all the way to the `L1Traversal` stage. async fn reset(&mut self, block_info: BlockInfo) -> anyhow::Result<()> { - self.tip = block_info; let system_config = self .l2_chain_provider - .system_config_by_number(self.tip.number, Arc::clone(&self.rollup_config)) + .system_config_by_number(block_info.number, Arc::clone(&self.rollup_config)) .await?; - match self.attributes.reset(self.tip, &system_config).await { + match self.attributes.reset(block_info, &system_config).await { Ok(()) => tracing::info!("Stages reset"), Err(StageError::Eof) => tracing::info!("Stages reset with EOF"), Err(err) => { @@ -101,8 +83,8 @@ where /// An error is expected when the underlying source closes. /// When [DerivationPipeline::step] returns [Ok(())], it should be called again, to continue the /// derivation process. - async fn step(&mut self) -> anyhow::Result<()> { - match self.attributes.next_attributes(self.cursor).await { + async fn step(&mut self, cursor: L2BlockInfo) -> anyhow::Result<()> { + match self.attributes.next_attributes(cursor).await { Ok(a) => { tracing::info!("attributes queue stage step returned l2 attributes"); tracing::info!("prepared L2 attributes: {:?}", a); @@ -115,7 +97,7 @@ where } // TODO: match on the EngineELSyncing error here and log Err(err) => { - tracing::error!("attributes queue step failed: {:?}", err); + tracing::warn!("attributes queue step failed: {:?}", err); return Err(anyhow::anyhow!(err)); } } diff --git a/crates/derive/src/pipeline/mod.rs b/crates/derive/src/pipeline/mod.rs index 948db5d09e..2d426d2b61 100644 --- a/crates/derive/src/pipeline/mod.rs +++ b/crates/derive/src/pipeline/mod.rs @@ -3,7 +3,7 @@ /// Re-export trait arguments. pub use crate::traits::{ ChainProvider, DataAvailabilityProvider, L2ChainProvider, NextAttributes, OriginAdvancer, - Pipeline, PreviousStage, ResetProvider, ResettableStage, + OriginProvider, Pipeline, PreviousStage, ResetProvider, ResettableStage, }; /// Re-export stage types that are needed as inputs. diff --git a/crates/derive/src/sources/ethereum.rs b/crates/derive/src/sources/ethereum.rs index e85ba05122..5fc4d45a20 100644 --- a/crates/derive/src/sources/ethereum.rs +++ b/crates/derive/src/sources/ethereum.rs @@ -41,7 +41,12 @@ where chain_provider: provider, blob_provider: blobs, ecotone_timestamp: cfg.ecotone_time, - signer: cfg.genesis.system_config.batcher_addr, + signer: cfg + .genesis + .system_config + .as_ref() + .map(|sc| sc.batcher_addr) + .unwrap_or_default(), batch_inbox_address: cfg.batch_inbox_address, } } @@ -83,7 +88,7 @@ mod tests { use alloy_consensus::TxEnvelope; use alloy_eips::eip2718::Decodable2718; use alloy_primitives::address; - use kona_primitives::{BlockInfo, RollupConfig}; + use kona_primitives::{BlockInfo, RollupConfig, SystemConfig}; use crate::{ sources::{EthereumDataSource, EthereumDataSourceVariant}, @@ -128,7 +133,8 @@ mod tests { let block_ref = BlockInfo { number: 10, ..Default::default() }; let mut cfg = RollupConfig::default(); - cfg.genesis.system_config.batcher_addr = batcher_address; + cfg.genesis.system_config = + Some(SystemConfig { batcher_addr: batcher_address, ..Default::default() }); cfg.batch_inbox_address = batch_inbox; // load a test batcher transaction diff --git a/crates/derive/src/stages/attributes_queue.rs b/crates/derive/src/stages/attributes_queue.rs index 4415354a40..a1ae39474c 100644 --- a/crates/derive/src/stages/attributes_queue.rs +++ b/crates/derive/src/stages/attributes_queue.rs @@ -7,7 +7,7 @@ use crate::{ RollupConfig, SingleBatch, StageError, StageResult, SystemConfig, }, }; -use alloc::boxed::Box; +use alloc::{boxed::Box, sync::Arc}; use async_trait::async_trait; use core::fmt::Debug; use tracing::info; @@ -49,7 +49,7 @@ where AB: AttributesBuilder + Debug, { /// The rollup config. - cfg: RollupConfig, + cfg: Arc, /// The previous stage of the derivation pipeline. prev: P, /// Whether the current batch is the last in its span. @@ -66,7 +66,7 @@ where AB: AttributesBuilder + Debug, { /// Create a new [AttributesQueue] stage. - pub fn new(cfg: RollupConfig, prev: P, builder: AB) -> Self { + pub fn new(cfg: Arc, prev: P, builder: AB) -> Self { Self { cfg, prev, is_last_in_span: false, batch: None, builder } } @@ -179,7 +179,7 @@ where P: AttributesProvider + PreviousStage + Debug, AB: AttributesBuilder + Debug, { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { self.prev.origin() } } @@ -215,7 +215,7 @@ mod tests { }, types::{BuilderError, RawTransaction}, }; - use alloc::{vec, vec::Vec}; + use alloc::{sync::Arc, vec, vec::Vec}; use alloy_primitives::b256; fn new_attributes_queue( @@ -226,7 +226,7 @@ mod tests { let cfg = cfg.unwrap_or_default(); let mock_batch_queue = new_attributes_provider(origin, batches); let mock_attributes_builder = MockAttributesBuilder::default(); - AttributesQueue::new(cfg, mock_batch_queue, mock_attributes_builder) + AttributesQueue::new(Arc::new(cfg), mock_batch_queue, mock_attributes_builder) } #[tokio::test] @@ -317,7 +317,7 @@ mod tests { 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); + let mut aq = AttributesQueue::new(Arc::new(cfg), mock, mock_builder); let parent = L2BlockInfo::default(); let txs = vec![RawTransaction::default(), RawTransaction::default()]; let batch = SingleBatch { transactions: txs.clone(), ..Default::default() }; @@ -342,7 +342,7 @@ mod tests { let mock = new_attributes_provider(None, vec![Ok(Default::default())]); let mut pa = L2PayloadAttributes::default(); let mock_builder = MockAttributesBuilder { attributes: vec![Ok(pa.clone())] }; - let mut aq = AttributesQueue::new(cfg, mock, mock_builder); + let mut aq = AttributesQueue::new(Arc::new(cfg), mock, mock_builder); // If we load the batch, we should get the last in span. // But it won't take it so it will be available in the next_attributes call. let _ = aq.load_batch(L2BlockInfo::default()).await.unwrap(); diff --git a/crates/derive/src/stages/batch_queue.rs b/crates/derive/src/stages/batch_queue.rs index 5fdf8a2185..a015865f90 100644 --- a/crates/derive/src/stages/batch_queue.rs +++ b/crates/derive/src/stages/batch_queue.rs @@ -306,8 +306,8 @@ where // Advance the origin if needed. // The entire pipeline has the same origin. // Batches prior to the l1 origin of the l2 safe head are not accepted. - if self.origin != self.prev.origin().copied() { - self.origin = self.prev.origin().cloned(); + if self.origin != self.prev.origin() { + self.origin = self.prev.origin(); if !origin_behind { let origin = self.origin.as_ref().ok_or_else(|| anyhow!("missing origin"))?; self.l1_blocks.push(*origin); @@ -388,7 +388,7 @@ where P: BatchQueueProvider + PreviousStage + Debug, BF: L2ChainProvider + Debug, { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { self.prev.origin() } } @@ -436,8 +436,8 @@ mod tests { }, traits::test_utils::TestL2ChainProvider, types::{ - BatchType, BlockID, Genesis, L1BlockInfoBedrock, L1BlockInfoTx, L2ExecutionPayload, - L2ExecutionPayloadEnvelope, + BatchType, BlockID, ChainGenesis, L1BlockInfoBedrock, L1BlockInfoTx, + L2ExecutionPayload, L2ExecutionPayloadEnvelope, }, }; use alloc::vec; @@ -518,7 +518,7 @@ mod tests { block_time: 100, max_sequencer_drift: 10000000, seq_window_size: 10000000, - genesis: Genesis { + genesis: ChainGenesis { l2: BlockID { number: 8, hash: payload_block_hash }, l1: BlockID { number: 16988980031808077784, ..Default::default() }, ..Default::default() diff --git a/crates/derive/src/stages/channel_bank.rs b/crates/derive/src/stages/channel_bank.rs index 078341fd4e..a2c778c2de 100644 --- a/crates/derive/src/stages/channel_bank.rs +++ b/crates/derive/src/stages/channel_bank.rs @@ -77,7 +77,7 @@ where /// Adds new L1 data to the channel bank. Should only be called after all data has been read. pub fn ingest_frame(&mut self, frame: Frame) -> StageResult<()> { - let origin = *self.origin().ok_or(StageError::MissingOrigin)?; + let origin = self.origin().ok_or(StageError::MissingOrigin)?; // Get the channel for the frame, or create a new one if it doesn't exist. let current_channel = self.channels.entry(frame.id).or_insert_with(|| { @@ -200,7 +200,7 @@ impl

OriginProvider for ChannelBank

where P: ChannelBankProvider + PreviousStage + Debug, { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { self.prev.origin() } } diff --git a/crates/derive/src/stages/channel_reader.rs b/crates/derive/src/stages/channel_reader.rs index ff81ff34f4..95f38200e3 100644 --- a/crates/derive/src/stages/channel_reader.rs +++ b/crates/derive/src/stages/channel_reader.rs @@ -12,7 +12,7 @@ use alloy_rlp::Decodable; use async_trait::async_trait; use core::fmt::Debug; use miniz_oxide::inflate::decompress_to_vec_zlib; -use tracing::error; +use tracing::warn; /// The [ChannelReader] provider trait. #[async_trait] @@ -80,7 +80,7 @@ where { async fn next_batch(&mut self) -> StageResult { if let Err(e) = self.set_batch_reader().await { - error!("Failed to set batch reader: {:?}", e); + warn!("Failed to set batch reader: {:?}", e); self.next_channel(); return Err(e); } @@ -104,7 +104,7 @@ impl

OriginProvider for ChannelReader

where P: ChannelReaderProvider + PreviousStage + Debug, { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { self.prev.origin() } } diff --git a/crates/derive/src/stages/frame_queue.rs b/crates/derive/src/stages/frame_queue.rs index 07586ffcb6..edb7e44180 100644 --- a/crates/derive/src/stages/frame_queue.rs +++ b/crates/derive/src/stages/frame_queue.rs @@ -10,7 +10,7 @@ use alloy_primitives::Bytes; use anyhow::anyhow; use async_trait::async_trait; use core::fmt::Debug; -use tracing::{debug, error}; +use tracing::{debug, error, warn}; /// Provides data frames for the [FrameQueue] stage. #[async_trait] @@ -79,7 +79,7 @@ where } } Err(e) => { - error!("Failed to retrieve data: {:?}", e); + warn!("Failed to retrieve data: {:?}", e); return Err(e); // Bubble up potential EOF error without wrapping. } } @@ -99,7 +99,7 @@ impl

OriginProvider for FrameQueue

where P: FrameQueueProvider + PreviousStage + Debug, { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { self.prev.origin() } } diff --git a/crates/derive/src/stages/l1_retrieval.rs b/crates/derive/src/stages/l1_retrieval.rs index 4fda215f80..c549f5f33c 100644 --- a/crates/derive/src/stages/l1_retrieval.rs +++ b/crates/derive/src/stages/l1_retrieval.rs @@ -110,7 +110,7 @@ where DAP: DataAvailabilityProvider, P: L1RetrievalProvider + PreviousStage, { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { self.prev.origin() } } @@ -154,7 +154,7 @@ mod tests { let dap = TestDAP { results: vec![], batch_inbox_address: Address::default() }; let retrieval = L1Retrieval::new(traversal, dap); let expected = BlockInfo::default(); - assert_eq!(retrieval.origin(), Some(&expected)); + assert_eq!(retrieval.origin(), Some(expected)); } #[tokio::test] diff --git a/crates/derive/src/stages/l1_traversal.rs b/crates/derive/src/stages/l1_traversal.rs index d9dda56b2e..6db6d7ec9a 100644 --- a/crates/derive/src/stages/l1_traversal.rs +++ b/crates/derive/src/stages/l1_traversal.rs @@ -111,8 +111,8 @@ impl OriginAdvancer for L1Traversal { } impl OriginProvider for L1Traversal { - fn origin(&self) -> Option<&BlockInfo> { - self.block.as_ref() + fn origin(&self) -> Option { + self.block } } @@ -127,7 +127,7 @@ impl ResettableStage for L1Traversal { async fn reset(&mut self, base: BlockInfo, cfg: &SystemConfig) -> StageResult<()> { self.block = Some(base); self.done = false; - self.system_config = *cfg; + self.system_config = cfg.clone(); Err(StageError::Eof) } } diff --git a/crates/derive/src/stages/test_utils/attributes_queue.rs b/crates/derive/src/stages/test_utils/attributes_queue.rs index 1e689ecbff..e85a806f59 100644 --- a/crates/derive/src/stages/test_utils/attributes_queue.rs +++ b/crates/derive/src/stages/test_utils/attributes_queue.rs @@ -44,8 +44,8 @@ pub struct MockAttributesProvider { } impl OriginProvider for MockAttributesProvider { - fn origin(&self) -> Option<&BlockInfo> { - self.origin.as_ref() + fn origin(&self) -> Option { + self.origin } } diff --git a/crates/derive/src/stages/test_utils/batch_queue.rs b/crates/derive/src/stages/test_utils/batch_queue.rs index 896add5ee5..6d345a5a17 100644 --- a/crates/derive/src/stages/test_utils/batch_queue.rs +++ b/crates/derive/src/stages/test_utils/batch_queue.rs @@ -25,8 +25,8 @@ impl MockBatchQueueProvider { } impl OriginProvider for MockBatchQueueProvider { - fn origin(&self) -> Option<&BlockInfo> { - self.origin.as_ref() + fn origin(&self) -> Option { + self.origin } } diff --git a/crates/derive/src/stages/test_utils/channel_bank.rs b/crates/derive/src/stages/test_utils/channel_bank.rs index 9da6717abc..c525280a5e 100644 --- a/crates/derive/src/stages/test_utils/channel_bank.rs +++ b/crates/derive/src/stages/test_utils/channel_bank.rs @@ -25,8 +25,8 @@ impl MockChannelBankProvider { } impl OriginProvider for MockChannelBankProvider { - fn origin(&self) -> Option<&BlockInfo> { - self.block_info.as_ref() + fn origin(&self) -> Option { + self.block_info } } diff --git a/crates/derive/src/stages/test_utils/channel_reader.rs b/crates/derive/src/stages/test_utils/channel_reader.rs index d43a4e8309..a300cdad64 100644 --- a/crates/derive/src/stages/test_utils/channel_reader.rs +++ b/crates/derive/src/stages/test_utils/channel_reader.rs @@ -26,8 +26,8 @@ impl MockChannelReaderProvider { } impl OriginProvider for MockChannelReaderProvider { - fn origin(&self) -> Option<&BlockInfo> { - self.block_info.as_ref() + fn origin(&self) -> Option { + self.block_info } } diff --git a/crates/derive/src/stages/test_utils/frame_queue.rs b/crates/derive/src/stages/test_utils/frame_queue.rs index 8349cfbc9e..21d1b6aa5c 100644 --- a/crates/derive/src/stages/test_utils/frame_queue.rs +++ b/crates/derive/src/stages/test_utils/frame_queue.rs @@ -24,7 +24,7 @@ impl MockFrameQueueProvider { } impl OriginProvider for MockFrameQueueProvider { - fn origin(&self) -> Option<&BlockInfo> { + fn origin(&self) -> Option { None } } diff --git a/crates/derive/src/traits/pipeline.rs b/crates/derive/src/traits/pipeline.rs index 03bb5f5890..7b7f3f49e4 100644 --- a/crates/derive/src/traits/pipeline.rs +++ b/crates/derive/src/traits/pipeline.rs @@ -1,25 +1,19 @@ //! Defines the interface for the core derivation pipeline. +use super::OriginProvider; use alloc::boxed::Box; use async_trait::async_trait; use kona_primitives::{BlockInfo, L2AttributesWithParent, L2BlockInfo}; /// This trait defines the interface for interacting with the derivation pipeline. #[async_trait] -pub trait Pipeline { +pub trait Pipeline: OriginProvider { + /// Returns the next [L2AttributesWithParent] from the pipeline. + fn next_attributes(&mut self) -> Option; + /// Resets the pipeline on the next [Pipeline::step] call. async fn reset(&mut self, origin: BlockInfo) -> anyhow::Result<()>; - /// Sets the L1 Origin of the pipeline. - fn set_origin(&mut self, origin: BlockInfo); - /// Attempts to progress the pipeline. - async fn step(&mut self) -> anyhow::Result<()>; - - /// Pops the next prepared [L2AttributesWithParent] from the pipeline. - fn pop(&mut self) -> Option; - - /// Updates the L2 Safe Head cursor of the pipeline. - /// This is used when fetching the next attributes. - fn update_cursor(&mut self, cursor: L2BlockInfo); + async fn step(&mut self, cursor: L2BlockInfo) -> anyhow::Result<()>; } diff --git a/crates/derive/src/traits/stages.rs b/crates/derive/src/traits/stages.rs index 3776f9a19e..bc849be48d 100644 --- a/crates/derive/src/traits/stages.rs +++ b/crates/derive/src/traits/stages.rs @@ -14,7 +14,7 @@ pub trait ResettableStage { /// Provides a method for accessing the pipeline's current L1 origin. pub trait OriginProvider { /// Returns the optional L1 [BlockInfo] origin. - fn origin(&self) -> Option<&BlockInfo>; + fn origin(&self) -> Option; } /// Defines a trait for advancing the L1 origin of the pipeline. diff --git a/crates/derive/src/types/batch/mod.rs b/crates/derive/src/types/batch/mod.rs index 58541377fb..ad7aeddd04 100644 --- a/crates/derive/src/types/batch/mod.rs +++ b/crates/derive/src/types/batch/mod.rs @@ -97,7 +97,7 @@ impl Batch { let mut raw_span_batch = RawSpanBatch::decode(r).map_err(DecodeError::SpanBatchError)?; let span_batch = raw_span_batch - .derive(cfg.block_time, cfg.genesis.timestamp, cfg.l2_chain_id) + .derive(cfg.block_time, cfg.genesis.l2_time, cfg.l2_chain_id) .map_err(DecodeError::SpanBatchError)?; Ok(Batch::Span(span_batch)) } diff --git a/crates/derive/src/types/batch/single_batch.rs b/crates/derive/src/types/batch/single_batch.rs index a7f19b8d56..eb427e3de2 100644 --- a/crates/derive/src/types/batch/single_batch.rs +++ b/crates/derive/src/types/batch/single_batch.rs @@ -165,39 +165,6 @@ impl SingleBatch { } } -// impl Encodable for SingleBatch { -// fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { -// self.parent_hash.encode(out); -// self.epoch_num.encode(out); -// self.epoch_hash.encode(out); -// self.timestamp.encode(out); -// self.transactions.encode(out); -// } -// } -// -// impl Decodable for SingleBatch { -// fn decode(rlp: &mut &[u8]) -> alloy_rlp::Result { -// let Header { list, payload_length } = Header::decode(rlp)?; -// -// if !list { -// return Err(alloy_rlp::Error::UnexpectedString); -// } -// let starting_length = rlp.len(); -// -// let parent_hash = BlockHash::decode(rlp)?; -// let epoch_num = u64::decode(rlp)?; -// let epoch_hash = BlockHash::decode(rlp)?; -// let timestamp = u64::decode(rlp)?; -// let transactions = Vec::::decode(rlp)?; -// -// if rlp.len() + payload_length != starting_length { -// return Err(alloy_rlp::Error::UnexpectedLength); -// } -// -// Ok(Self { parent_hash, epoch_num, epoch_hash, timestamp, transactions }) -// } -// } - #[cfg(test)] mod tests { use super::SingleBatch; diff --git a/crates/derive/src/types/batch/span_batch/batch.rs b/crates/derive/src/types/batch/span_batch/batch.rs index 2102cadaed..a5614dd394 100644 --- a/crates/derive/src/types/batch/span_batch/batch.rs +++ b/crates/derive/src/types/batch/span_batch/batch.rs @@ -416,7 +416,9 @@ mod tests { use crate::{ stages::test_utils::{CollectingLayer, TraceStorage}, traits::test_utils::TestL2ChainProvider, - types::{BlockID, Genesis, L2ExecutionPayload, L2ExecutionPayloadEnvelope, RawTransaction}, + types::{ + BlockID, ChainGenesis, L2ExecutionPayload, L2ExecutionPayloadEnvelope, RawTransaction, + }, }; use alloc::vec; use alloy_primitives::{b256, Bytes, B256}; @@ -1444,7 +1446,7 @@ mod tests { seq_window_size: 100, delta_time: Some(0), block_time: 10, - genesis: Genesis { + genesis: ChainGenesis { l2: BlockID { number: 41, hash: payload_block_hash }, ..Default::default() }, @@ -1514,7 +1516,7 @@ mod tests { seq_window_size: 100, delta_time: Some(0), block_time: 10, - genesis: Genesis { + genesis: ChainGenesis { l2: BlockID { number: 41, hash: payload_block_hash }, l1: BlockID { number: 10, ..Default::default() }, ..Default::default() diff --git a/crates/plasma/src/online.rs b/crates/plasma/src/online.rs index 60b6227d45..cf6da8748b 100644 --- a/crates/plasma/src/online.rs +++ b/crates/plasma/src/online.rs @@ -8,10 +8,7 @@ use alloc::boxed::Box; use alloy_primitives::Bytes; use async_trait::async_trait; use kona_derive::online::AlloyChainProvider; -use kona_primitives::{ - block::{BlockID, BlockInfo}, - system_config::SystemConfig, -}; +use kona_primitives::{BlockID, BlockInfo, SystemConfig}; /// An Online Plasma Input Fetcher. #[derive(Debug, Clone)] diff --git a/crates/plasma/src/source.rs b/crates/plasma/src/source.rs index c9b8de50e5..7fec8aa71f 100644 --- a/crates/plasma/src/source.rs +++ b/crates/plasma/src/source.rs @@ -12,9 +12,8 @@ use anyhow::anyhow; use async_trait::async_trait; use kona_derive::{ traits::{AsyncIterator, ChainProvider}, - types::{ResetError, StageError, StageResult}, + types::{BlockID, ResetError, StageError, StageResult}, }; -use kona_primitives::block::BlockID; /// A plasma data iterator. #[derive(Debug, Clone)] diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index f0e8ce8f63..8e505d2c82 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -16,6 +16,9 @@ alloy-primitives = { workspace = true, features = ["rlp"] } alloy-eips.workspace = true op-alloy-consensus.workspace = true +# Superchain Registry +superchain-primitives = { git = "https://github.com/ethereum-optimism/superchain-registry", branch = "main", default-features = false } + # Alloy Types alloy-sol-types = { version = "0.7.6", default-features = false } @@ -27,4 +30,4 @@ serde_json = { version = "1.0.117", default-features = false } [features] default = ["serde"] -serde = ["dep:serde"] +serde = ["dep:serde", "superchain-primitives/serde"] diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 6d9fdd609f..81138e2b0c 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -1,9 +1,10 @@ //! This module contains the various Block types. +use crate::BlockID; use alloc::vec::Vec; use alloy_consensus::{Header, TxEnvelope}; use alloy_eips::eip4895::Withdrawal; -use alloy_primitives::{BlockHash, BlockNumber, B256}; +use alloy_primitives::B256; use alloy_rlp::{RlpDecodable, RlpEncodable}; use op_alloy_consensus::OpTxEnvelope; @@ -46,22 +47,6 @@ impl core::fmt::Display for BlockInfo { } } -/// Block ID identifies a block by its hash and number -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] -pub struct BlockID { - /// The block hash - pub hash: BlockHash, - /// The block number - pub number: BlockNumber, -} - -impl core::fmt::Display for BlockID { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{{ hash: {}, number: {} }}", self.hash, self.number) - } -} - /// L2 Block Header Info #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] diff --git a/crates/primitives/src/block_info.rs b/crates/primitives/src/block_info.rs index 80995f2147..f295353df9 100644 --- a/crates/primitives/src/block_info.rs +++ b/crates/primitives/src/block_info.rs @@ -126,7 +126,7 @@ impl L1BlockInfoTx { if rollup_config.is_ecotone_active(l2_block_time) && rollup_config.ecotone_time.unwrap_or_default() != l2_block_time { - let scalar = system_config.l1_fee_scalar.to_be_bytes::<32>(); + let scalar = system_config.scalar.to_be_bytes::<32>(); let blob_base_fee_scalar = (scalar[0] == L1_SCALAR_ECOTONE) .then(|| { Ok::(u32::from_be_bytes( @@ -161,8 +161,8 @@ impl L1BlockInfoTx { block_hash: l1_header.hash_slow(), sequence_number, batcher_address: system_config.batcher_addr, - l1_fee_overhead: system_config.l1_fee_overhead, - l1_fee_scalar: system_config.l1_fee_scalar, + l1_fee_overhead: system_config.overhead, + l1_fee_scalar: system_config.scalar, })) } } @@ -473,8 +473,8 @@ mod test { assert_eq!(l1_info.block_hash, l1_header.hash_slow()); assert_eq!(l1_info.sequence_number, sequence_number); assert_eq!(l1_info.batcher_address, system_config.batcher_addr); - assert_eq!(l1_info.l1_fee_overhead, system_config.l1_fee_overhead); - assert_eq!(l1_info.l1_fee_scalar, system_config.l1_fee_scalar); + assert_eq!(l1_info.l1_fee_overhead, system_config.overhead); + assert_eq!(l1_info.l1_fee_scalar, system_config.scalar); } #[test] @@ -506,7 +506,7 @@ mod test { assert_eq!(l1_info.batcher_address, system_config.batcher_addr); assert_eq!(l1_info.blob_base_fee, l1_header.blob_fee().unwrap_or(1)); - let scalar = system_config.l1_fee_scalar.to_be_bytes::<32>(); + let scalar = system_config.scalar.to_be_bytes::<32>(); let blob_base_fee_scalar = (scalar[0] == L1_SCALAR_ECOTONE) .then(|| { u32::from_be_bytes( diff --git a/crates/primitives/src/genesis.rs b/crates/primitives/src/genesis.rs deleted file mode 100644 index ad821b446b..0000000000 --- a/crates/primitives/src/genesis.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! This module contains the [Genesis] type. - -use crate::{block::BlockID, system_config::SystemConfig}; - -/// Represents the genesis state of the rollup. -#[derive(Debug, Clone, Copy, Default)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Genesis { - /// The L1 block that the rollup starts *after* (no derived transactions) - pub l1: BlockID, - /// The L2 block the rollup starts from (no transactions, pre-configured state) - pub l2: BlockID, - /// Timestamp of the L2 block. - pub timestamp: u64, - /// Initial system configuration values. - /// The L2 genesis block may not include transactions, and thus cannot encode the config - /// values, unlike later L2 blocks. - pub system_config: SystemConfig, -} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 8f4619bd70..fc4fc0c03c 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -4,6 +4,9 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![no_std] +// Re-export superchain-primitives +pub use superchain_primitives::*; + extern crate alloc; /// Re-export the [Withdrawal] type from the [alloy_eips] crate. @@ -12,7 +15,7 @@ extern crate alloc; pub use alloy_eips::eip4895::Withdrawal; pub mod block; -pub use block::{Block, BlockID, BlockInfo, BlockKind, L2BlockInfo, OpBlock}; +pub use block::{Block, BlockInfo, BlockKind, L2BlockInfo, OpBlock}; pub mod block_info; pub use block_info::{L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoTx}; @@ -26,22 +29,10 @@ pub use deposits::{ L1InfoDepositSource, UpgradeDepositSource, UserDepositSource, DEPOSIT_EVENT_ABI_HASH, }; -pub mod genesis; -pub use genesis::Genesis; - -pub mod params; -pub use params::*; - pub mod payload; pub use payload::{ L2ExecutionPayload, L2ExecutionPayloadEnvelope, PAYLOAD_MEM_FIXED_COST, PAYLOAD_TX_MEM_OVERHEAD, }; -pub mod rollup_config; -pub use rollup_config::RollupConfig; - pub mod attributes; pub use attributes::{L2AttributesWithParent, L2PayloadAttributes}; - -pub mod system_config; -pub use system_config::{SystemAccounts, SystemConfig, SystemConfigUpdateType}; diff --git a/crates/primitives/src/params.rs b/crates/primitives/src/params.rs deleted file mode 100644 index 488e9553e6..0000000000 --- a/crates/primitives/src/params.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! This module contains the parameters and identifying types for the derivation pipeline. - -use alloy_primitives::{b256, B256}; - -/// `keccak256("ConfigUpdate(uint256,uint8,bytes)")` -pub const CONFIG_UPDATE_TOPIC: B256 = - b256!("1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be"); - -/// The initial version of the system config event log. -pub const CONFIG_UPDATE_EVENT_VERSION_0: B256 = B256::ZERO; diff --git a/crates/primitives/src/payload.rs b/crates/primitives/src/payload.rs index a7cf5bbf06..52334b001d 100644 --- a/crates/primitives/src/payload.rs +++ b/crates/primitives/src/payload.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use alloy_eips::eip2718::{Decodable2718, Encodable2718}; -use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; +use alloy_primitives::{Address, Bloom, Bytes, B256}; use anyhow::Result; use op_alloy_consensus::{OpTxEnvelope, OpTxType}; @@ -174,7 +174,11 @@ impl L2ExecutionPayloadEnvelope { if execution_payload.block_hash != rollup_config.genesis.l2.hash { anyhow::bail!("Invalid genesis hash"); } - return Ok(rollup_config.genesis.system_config); + return rollup_config + .genesis + .system_config + .clone() + .ok_or_else(|| anyhow::anyhow!("Missing system config in genesis block")); } if execution_payload.transactions.is_empty() { @@ -215,9 +219,11 @@ impl L2ExecutionPayloadEnvelope { Ok(SystemConfig { batcher_addr: l1_info.batcher_address(), - l1_fee_overhead: l1_info.l1_fee_overhead(), - l1_fee_scalar, - gas_limit: U256::from(execution_payload.gas_limit), + overhead: l1_info.l1_fee_overhead(), + scalar: l1_fee_scalar, + gas_limit: execution_payload.gas_limit as u64, + base_fee_scalar: None, + blob_base_fee_scalar: None, }) } } diff --git a/crates/primitives/src/rollup_config.rs b/crates/primitives/src/rollup_config.rs deleted file mode 100644 index 9d7962521f..0000000000 --- a/crates/primitives/src/rollup_config.rs +++ /dev/null @@ -1,200 +0,0 @@ -//! This module contains the [RollupConfig] type. - -use crate::genesis::Genesis; -use alloy_eips::eip1559::BaseFeeParams; -use alloy_primitives::Address; - -/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism -/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. -pub const OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u128 = 50; - -/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism Canyon -/// hardfork. -pub const OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON: u128 = 250; - -/// Base fee max change denominator for Optimism Mainnet as defined in the Optimism -/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. -pub const OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 6; - -/// Base fee max change denominator for Optimism Sepolia as defined in the Optimism -/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. -pub const OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR: u128 = 50; - -/// Base fee max change denominator for Optimism Sepolia as defined in the Optimism Canyon -/// hardfork. -pub const OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON: u128 = 250; - -/// Base fee max change denominator for Optimism Sepolia as defined in the Optimism -/// [transaction costs](https://community.optimism.io/docs/developers/build/differences/#transaction-costs) doc. -pub const OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER: u128 = 10; - -/// Get the base fee parameters for Optimism Sepolia. -pub const OP_SEPOLIA_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, - elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Sepolia (post Canyon). -pub const OP_SEPOLIA_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, - elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Mainnet. -pub const OP_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, - elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Mainnet (post Canyon). -pub const OP_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, - elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// The Rollup configuration. -#[derive(Debug, Clone, Copy, Default)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct RollupConfig { - /// The genesis state of the rollup. - pub genesis: Genesis, - /// The block time of the L2, in seconds. - pub block_time: u64, - /// Sequencer batches may not be more than MaxSequencerDrift seconds after - /// the L1 timestamp of the sequencing window end. - /// - /// Note: When L1 has many 1 second consecutive blocks, and L2 grows at fixed 2 seconds, - /// the L2 time may still grow beyond this difference. - pub max_sequencer_drift: u64, - /// The sequencer window size. - pub seq_window_size: u64, - /// Number of L1 blocks between when a channel can be opened and when it can be closed. - pub channel_timeout: u64, - /// The L1 chain ID - pub l1_chain_id: u64, - /// The L2 chain ID - pub l2_chain_id: u64, - /// `regolith_time` sets the activation time of the Regolith network-upgrade: - /// a pre-mainnet Bedrock change that addresses findings of the Sherlock contest related to - /// deposit attributes. "Regolith" is the loose deposited rock that sits on top of Bedrock. - /// Active if regolith_time != None && L2 block timestamp >= Some(regolith_time), inactive - /// otherwise. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub regolith_time: Option, - /// `canyon_time` sets the activation time of the Canyon network upgrade. - /// Active if `canyon_time` != None && L2 block timestamp >= Some(canyon_time), inactive - /// otherwise. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub canyon_time: Option, - /// `delta_time` sets the activation time of the Delta network upgrade. - /// Active if `delta_time` != None && L2 block timestamp >= Some(delta_time), inactive - /// otherwise. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub delta_time: Option, - /// `ecotone_time` sets the activation time of the Ecotone network upgrade. - /// Active if `ecotone_time` != None && L2 block timestamp >= Some(ecotone_time), inactive - /// otherwise. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub ecotone_time: Option, - /// `fjord_time` sets the activation time of the Fjord network upgrade. - /// Active if `fjord_time` != None && L2 block timestamp >= Some(fjord_time), inactive - /// otherwise. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub fjord_time: Option, - /// `interop_time` sets the activation time for an experimental feature-set, activated like a - /// hardfork. Active if `interop_time` != None && L2 block timestamp >= Some(interop_time), - /// inactive otherwise. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub interop_time: Option, - /// `batch_inbox_address` is the L1 address that batches are sent to. - pub batch_inbox_address: Address, - /// `deposit_contract_address` is the L1 address that deposits are sent to. - pub deposit_contract_address: Address, - /// `l1_system_config_address` is the L1 address that the system config is stored at. - pub l1_system_config_address: Address, - /// `protocol_versions_address` is the L1 address that the protocol versions are stored at. - pub protocol_versions_address: Address, - /// `blobs_enabled_l1_timestamp` is the timestamp to start reading blobs as a batch data - /// source. Optional. - #[cfg_attr( - feature = "serde", - serde(rename = "blobs_data", skip_serializing_if = "Option::is_none") - )] - pub blobs_enabled_l1_timestamp: Option, - /// `da_challenge_address` is the L1 address that the data availability challenge contract is - /// stored at. - #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] - pub da_challenge_address: Option

, -} - -impl RollupConfig { - /// Returns true if Regolith is active at the given timestamp. - pub fn is_regolith_active(&self, timestamp: u64) -> bool { - self.regolith_time.map_or(false, |t| timestamp >= t) - } - - /// Returns true if Canyon is active at the given timestamp. - pub fn is_canyon_active(&self, timestamp: u64) -> bool { - self.canyon_time.map_or(false, |t| timestamp >= t) - } - - /// Returns true if Delta is active at the given timestamp. - pub fn is_delta_active(&self, timestamp: u64) -> bool { - self.delta_time.map_or(false, |t| timestamp >= t) - } - - /// Returns true if Ecotone is active at the given timestamp. - pub fn is_ecotone_active(&self, timestamp: u64) -> bool { - self.ecotone_time.map_or(false, |t| timestamp >= t) - } - - /// Returns true if Fjord is active at the given timestamp. - pub fn is_fjord_active(&self, timestamp: u64) -> bool { - self.fjord_time.map_or(false, |t| timestamp >= t) - } - - /// Returns true if Interop is active at the given timestamp. - pub fn is_interop_active(&self, timestamp: u64) -> bool { - self.interop_time.map_or(false, |t| timestamp >= t) - } - - /// Returns true if a DA Challenge proxy Address is provided in the rollup config and the - /// address is not zero. - pub fn is_plasma_enabled(&self) -> bool { - self.da_challenge_address.map_or(false, |addr| !addr.is_zero()) - } - - /// Returns the base fee parameters for the given rollup configuration. - /// - /// TODO: Consider chain-specific base fee params (i.e. Sepolia vs. Mainnet). - pub fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams { - if self.is_canyon_active(timestamp) { - OP_CANYON_BASE_FEE_PARAMS - } else { - OP_BASE_FEE_PARAMS - } - } - - /// Checks the scalar value in Ecotone. - pub fn check_ecotone_l1_system_config_scalar(scalar: [u8; 32]) -> Result<(), &'static str> { - let version_byte = scalar[0]; - match version_byte { - 0 => { - if scalar[1..28] != [0; 27] { - return Err("Bedrock scalar padding not empty"); - } - Ok(()) - } - 1 => { - if scalar[1..24] != [0; 23] { - return Err("Invalid version 1 scalar padding"); - } - Ok(()) - } - _ => { - // ignore the event if it's an unknown scalar format - Err("Unrecognized scalar version") - } - } - } -} diff --git a/crates/primitives/src/system_config.rs b/crates/primitives/src/system_config.rs deleted file mode 100644 index 24a100e79f..0000000000 --- a/crates/primitives/src/system_config.rs +++ /dev/null @@ -1,381 +0,0 @@ -//! This module contains the [SystemConfig] type. - -use crate::{ - params::{CONFIG_UPDATE_EVENT_VERSION_0, CONFIG_UPDATE_TOPIC}, - rollup_config::RollupConfig, -}; -use alloy_consensus::Receipt; -use alloy_primitives::{address, Address, Log, U256}; -use alloy_sol_types::{sol, SolType}; -use anyhow::{anyhow, bail, Result}; - -/// Optimism system config contract values -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] -pub struct SystemConfig { - /// Batch sender address - pub batcher_addr: Address, - /// L2 gas limit - pub gas_limit: U256, - /// Fee overhead - #[cfg_attr(feature = "serde", serde(rename = "overhead"))] - pub l1_fee_overhead: U256, - /// Fee scalar - #[cfg_attr(feature = "serde", serde(rename = "scalar"))] - pub l1_fee_scalar: U256, -} - -/// Represents type of update to the system config. -#[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, -} - -impl TryFrom for SystemConfigUpdateType { - type Error = anyhow::Error; - - fn try_from(value: u64) -> core::prelude::v1::Result { - match value { - 0 => Ok(SystemConfigUpdateType::Batcher), - 1 => Ok(SystemConfigUpdateType::GasConfig), - 2 => Ok(SystemConfigUpdateType::GasLimit), - 3 => Ok(SystemConfigUpdateType::UnsafeBlockSigner), - _ => bail!("Invalid SystemConfigUpdateType value: {}", value), - } - } -} - -impl SystemConfig { - /// Filters all L1 receipts to find config updates and applies the config updates. - pub fn update_with_receipts( - &mut self, - receipts: &[Receipt], - rollup_config: &RollupConfig, - l1_time: u64, - ) -> Result<()> { - for receipt in receipts { - if !receipt.status { - continue; - } - - receipt.logs.iter().try_for_each(|log| { - let topics = log.topics(); - if log.address == rollup_config.l1_system_config_address && - !topics.is_empty() && - topics[0] == CONFIG_UPDATE_TOPIC - { - if let Err(e) = self.process_config_update_log(log, rollup_config, l1_time) { - anyhow::bail!("Failed to process config update log: {:?}", e); - } - } - Ok::<(), anyhow::Error>(()) - })?; - } - Ok::<(), anyhow::Error>(()) - } - - /// Decodes an EVM log entry emitted by the system config contract and applies it as a - /// [SystemConfig] change. - /// - /// Parse log data for: - /// - /// ```text - /// event ConfigUpdate( - /// uint256 indexed version, - /// UpdateType indexed updateType, - /// bytes data - /// ); - /// ``` - fn process_config_update_log( - &mut self, - log: &Log, - rollup_config: &RollupConfig, - l1_time: u64, - ) -> Result<()> { - if log.topics().len() < 3 { - bail!("Invalid config update log: not enough topics"); - } - if log.topics()[0] != CONFIG_UPDATE_TOPIC { - bail!("Invalid config update log: invalid topic"); - } - - // Parse the config update log - let version = log.topics()[1]; - if version != CONFIG_UPDATE_EVENT_VERSION_0 { - bail!("Invalid config update log: unsupported version"); - } - let update_type = u64::from_be_bytes( - log.topics()[2].as_slice()[24..] - .try_into() - .map_err(|_| anyhow!("Failed to convert update type to u64"))?, - ); - let log_data = log.data.data.as_ref(); - - match update_type.try_into()? { - SystemConfigUpdateType::Batcher => { - if log_data.len() != 96 { - bail!("Invalid config update log: invalid data length"); - } - - let pointer = ::abi_decode(&log_data[0..32], true) - .map_err(|_| anyhow!("Failed to decode batcher update log"))?; - if pointer != 32 { - bail!("Invalid config update log: invalid data pointer"); - } - let length = ::abi_decode(&log_data[32..64], true) - .map_err(|_| anyhow!("Failed to decode batcher update log"))?; - if length != 32 { - bail!("Invalid config update log: invalid data length"); - } - - let batcher_address = - ::abi_decode(&log.data.data.as_ref()[64..], true) - .map_err(|_| anyhow!("Failed to decode batcher update log"))?; - self.batcher_addr = batcher_address; - } - SystemConfigUpdateType::GasConfig => { - if log_data.len() != 128 { - bail!("Invalid config update log: invalid data length"); - } - - let pointer = ::abi_decode(&log_data[0..32], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data pointer"))?; - if pointer != 32 { - bail!("Invalid config update log: invalid data pointer"); - } - let length = ::abi_decode(&log_data[32..64], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data length"))?; - if length != 64 { - bail!("Invalid config update log: invalid data length"); - } - - let overhead = ::abi_decode(&log_data[64..96], true) - .map_err(|_| anyhow!("Invalid config update log: invalid overhead"))?; - let scalar = ::abi_decode(&log_data[96..], true) - .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()) - .is_err() - { - // ignore invalid scalars, retain the old system-config scalar - return Ok(()); - } - - // retain the scalar data in encoded form - self.l1_fee_scalar = scalar; - // zero out the overhead, it will not affect the state-transition after Ecotone - self.l1_fee_overhead = U256::ZERO; - } else { - self.l1_fee_scalar = scalar; - self.l1_fee_overhead = overhead; - } - } - SystemConfigUpdateType::GasLimit => { - if log_data.len() != 96 { - bail!("Invalid config update log: invalid data length"); - } - - let pointer = ::abi_decode(&log_data[0..32], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data pointer"))?; - if pointer != 32 { - bail!("Invalid config update log: invalid data pointer"); - } - let length = ::abi_decode(&log_data[32..64], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data length"))?; - if length != 32 { - bail!("Invalid config update log: invalid data length"); - } - - let gas_limit = ::abi_decode(&log_data[64..], true) - .map_err(|_| anyhow!("Invalid config update log: invalid gas limit"))?; - self.gas_limit = gas_limit; - } - SystemConfigUpdateType::UnsafeBlockSigner => { - // Ignored in derivation - } - } - - Ok(()) - } -} - -/// System accounts -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct SystemAccounts { - /// The address that can deposit attributes - pub attributes_depositor: Address, - /// The address of the attributes predeploy - pub attributes_predeploy: Address, - /// The address of the fee vault - pub fee_vault: Address, -} - -impl Default for SystemAccounts { - fn default() -> Self { - Self { - attributes_depositor: address!("deaddeaddeaddeaddeaddeaddeaddeaddead0001"), - attributes_predeploy: address!("4200000000000000000000000000000000000015"), - fee_vault: address!("4200000000000000000000000000000000000011"), - } - } -} - -#[cfg(test)] -mod test { - use crate::genesis::Genesis; - - use super::*; - use alloc::vec; - use alloy_primitives::{b256, hex, LogData, B256}; - - extern crate std; - - fn mock_rollup_config(system_config: SystemConfig) -> RollupConfig { - RollupConfig { - genesis: Genesis { - l1: crate::block::BlockID::default(), - l2: crate::block::BlockID::default(), - timestamp: 0, - system_config, - }, - block_time: 2, - max_sequencer_drift: 0, - seq_window_size: 0, - channel_timeout: 0, - l1_chain_id: 1, - l2_chain_id: 10, - regolith_time: Some(0), - canyon_time: Some(0), - delta_time: Some(0), - ecotone_time: Some(10), - fjord_time: Some(0), - interop_time: Some(0), - batch_inbox_address: Address::ZERO, - deposit_contract_address: Address::ZERO, - l1_system_config_address: Address::ZERO, - protocol_versions_address: Address::ZERO, - blobs_enabled_l1_timestamp: Some(0), - da_challenge_address: Some(Address::ZERO), - } - } - - #[test] - fn test_system_config_update_batcher_log() { - const UPDATE_TYPE: B256 = - b256!("0000000000000000000000000000000000000000000000000000000000000000"); - - let mut system_config = SystemConfig::default(); - let rollup_config = mock_rollup_config(system_config); - - let update_log = Log { - address: Address::ZERO, - data: LogData::new_unchecked( - vec![ - CONFIG_UPDATE_TOPIC, - CONFIG_UPDATE_EVENT_VERSION_0, - UPDATE_TYPE, - ], - hex!("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000beef").into() - ) - }; - - // Update the batcher address. - system_config.process_config_update_log(&update_log, &rollup_config, 0).unwrap(); - - assert_eq!( - system_config.batcher_addr, - address!("000000000000000000000000000000000000bEEF") - ); - } - - #[test] - fn test_system_config_update_gas_config_log() { - const UPDATE_TYPE: B256 = - b256!("0000000000000000000000000000000000000000000000000000000000000001"); - - let mut system_config = SystemConfig::default(); - let rollup_config = mock_rollup_config(system_config); - - let update_log = Log { - address: Address::ZERO, - data: LogData::new_unchecked( - vec![ - CONFIG_UPDATE_TOPIC, - CONFIG_UPDATE_EVENT_VERSION_0, - UPDATE_TYPE, - ], - hex!("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000babe000000000000000000000000000000000000000000000000000000000000beef").into() - ) - }; - - // Update the batcher address. - system_config.process_config_update_log(&update_log, &rollup_config, 0).unwrap(); - - assert_eq!(system_config.l1_fee_overhead, U256::from(0xbabe)); - assert_eq!(system_config.l1_fee_scalar, U256::from(0xbeef)); - } - - #[test] - fn test_system_config_update_gas_config_log_ecotone() { - const UPDATE_TYPE: B256 = - b256!("0000000000000000000000000000000000000000000000000000000000000001"); - - let mut system_config = SystemConfig::default(); - let rollup_config = mock_rollup_config(system_config); - - let update_log = Log { - address: Address::ZERO, - data: LogData::new_unchecked( - vec![ - CONFIG_UPDATE_TOPIC, - CONFIG_UPDATE_EVENT_VERSION_0, - UPDATE_TYPE, - ], - hex!("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000babe000000000000000000000000000000000000000000000000000000000000beef").into() - ) - }; - - // Update the batcher address. - system_config.process_config_update_log(&update_log, &rollup_config, 10).unwrap(); - - assert_eq!(system_config.l1_fee_overhead, U256::from(0)); - assert_eq!(system_config.l1_fee_scalar, U256::from(0xbeef)); - } - - #[test] - fn test_system_config_update_gas_limit_log() { - const UPDATE_TYPE: B256 = - b256!("0000000000000000000000000000000000000000000000000000000000000002"); - - let mut system_config = SystemConfig::default(); - let rollup_config = mock_rollup_config(system_config); - - let update_log = Log { - address: Address::ZERO, - data: LogData::new_unchecked( - vec![ - CONFIG_UPDATE_TOPIC, - CONFIG_UPDATE_EVENT_VERSION_0, - UPDATE_TYPE, - ], - hex!("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000beef").into() - ) - }; - - // Update the batcher address. - system_config.process_config_update_log(&update_log, &rollup_config, 0).unwrap(); - - assert_eq!(system_config.gas_limit, U256::from(0xbeef)); - } -}