From ef12f7df57fc0ab79c15de3420c7da8aa8f222ba Mon Sep 17 00:00:00 2001 From: refcell Date: Tue, 30 Apr 2024 09:25:53 -0700 Subject: [PATCH 1/5] chore(l1): alloy type port --- src/derive/stages/attributes.rs | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 617c6a6..1ee0b78 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -393,37 +393,8 @@ pub struct UserDeposited { impl UserDeposited { /// Creates a new [UserDeposited] from the given data. - pub fn new( - log: alloy_rpc_types::Log, - l1_block_num: u64, - l1_block_hash: alloy_primitives::B256, - log_index: alloy_primitives::U256, - ) -> Result { - let opaque_data = decode(&[ParamType::Bytes], &log.data().data)?[0] - .clone() - .into_bytes() - .ok_or(eyre::eyre!("invalid data"))?; - - let from = Address::from_slice(log.topics()[1].as_slice()); - let to = Address::from_slice(log.topics()[2].as_slice()); - let mint = U256::from_big_endian(&opaque_data[0..32]); - let value = U256::from_big_endian(&opaque_data[32..64]); - let gas = u64::from_be_bytes(opaque_data[64..72].try_into()?); - let is_creation = opaque_data[72] != 0; - let data = opaque_data[73..].to_vec(); - - Ok(Self { - from, - to, - mint, - value, - gas, - is_creation, - data, - l1_block_num, - l1_block_hash: H256::from_slice(l1_block_hash.as_slice()), - log_index: U256::from_big_endian(&log_index.to_be_bytes::<32>()), - }) + pub fn new(log: alloy_rpc_types::Log) -> Result { + Self::try_from(log) } } From c36c66e8cba31ede15a845524076b204a57cf797 Mon Sep 17 00:00:00 2001 From: refcell Date: Tue, 30 Apr 2024 16:53:02 -0700 Subject: [PATCH 2/5] chore(drive): alloy type port --- src/common/mod.rs | 31 +-- src/config/mod.rs | 6 +- src/derive/stages/attributes.rs | 3 +- src/derive/stages/batches.rs | 14 +- src/derive/stages/single_batch.rs | 35 +-- src/driver/engine_driver.rs | 45 ++-- src/driver/info.rs | 35 +-- src/driver/mod.rs | 426 +----------------------------- src/driver/node_driver.rs | 408 ++++++++++++++++++++++++++++ src/driver/types.rs | 167 ++++++------ 10 files changed, 577 insertions(+), 593 deletions(-) create mode 100644 src/driver/node_driver.rs diff --git a/src/common/mod.rs b/src/common/mod.rs index 4c0c76d..e4407a4 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,10 +1,7 @@ use std::fmt::Debug; use alloy_primitives::B256; -use ethers::{ - types::{Block, Transaction}, - utils::rlp::{Decodable, DecoderError, Rlp}, -}; +use alloy_rpc_types::Block; use eyre::Result; use figment::value::{Dict, Tag, Value}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; @@ -29,7 +26,7 @@ pub struct BlockInfo { } /// A raw transaction -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, alloy_rlp::RlpDecodable, alloy_rlp::RlpEncodable, PartialEq, Eq)] pub struct RawTransaction(pub Vec); /// L1 epoch block @@ -57,23 +54,25 @@ impl From for Value { } } -impl TryFrom> for BlockInfo { +impl TryFrom for BlockInfo { type Error = eyre::Report; /// Converts a [Block] to [BlockInfo] - fn try_from(block: Block) -> Result { + fn try_from(block: Block) -> Result { let number = block + .header .number .ok_or(eyre::eyre!("block not included"))? - .as_u64(); + .try_into()?; - let hash = block.hash.ok_or(eyre::eyre!("block not included"))?; + let hash = block.header.hash.ok_or(eyre::eyre!("block not included"))?; + let timestamp = block.header.timestamp.try_into()?; Ok(BlockInfo { number, - hash: B256::from_slice(hash.as_bytes()), - parent_hash: B256::from_slice(block.parent_hash.as_bytes()), - timestamp: block.timestamp.as_u64(), + hash, + parent_hash: block.header.parent_hash, + timestamp, }) } } @@ -111,14 +110,6 @@ impl From<&AttributesDepositedCall> for Epoch { } } -impl Decodable for RawTransaction { - /// Decodes RLP encoded bytes into [RawTransaction] bytes - fn decode(rlp: &Rlp) -> Result { - let tx_bytes: Vec = rlp.as_val()?; - Ok(Self(tx_bytes)) - } -} - impl Debug for RawTransaction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "0x{}", hex::encode(&self.0)) diff --git a/src/config/mod.rs b/src/config/mod.rs index b0d02e3..827adcc 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,6 +1,6 @@ use std::{fmt, iter, path::PathBuf, process::exit, str::FromStr}; -use alloy_primitives::{Address, B256, U256}; +use alloy_primitives::{Address, B256, U64, U256}; use figment::{ providers::{Format, Serialized, Toml}, Figment, @@ -293,13 +293,13 @@ impl ChainConfig { } /// Returns true if the block is the first block subject to the Ecotone hardfork - pub fn is_ecotone_activation_block(&self, l2_block_timestamp: u64) -> bool { + pub fn is_ecotone_activation_block(&self, l2_block_timestamp: U64) -> bool { l2_block_timestamp == self.ecotone_time } /// Returns true if Ecotone hardfork is active but the block is not the /// first block subject to the hardfork. Ecotone activation at genesis does not count. - pub fn is_ecotone_but_not_first_block(&self, l2_block_timestamp: u64) -> bool { + pub fn is_ecotone_but_not_first_block(&self, l2_block_timestamp: U64) -> bool { let is_ecotone = l2_block_timestamp >= self.ecotone_time; is_ecotone && !self.is_ecotone_activation_block(l2_block_timestamp) diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 1ee0b78..3729ffb 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -6,6 +6,7 @@ use ethers::utils::{keccak256, rlp::Encodable, rlp::RlpStream}; use eyre::Result; +use alloy_primitives::U64; use crate::common::{Epoch, RawTransaction}; use crate::config::{Config, SystemAccounts}; use crate::derive::state::State; @@ -136,7 +137,7 @@ impl Attributes { if self .config .chain - .is_ecotone_activation_block(input.timestamp) + .is_ecotone_activation_block(U64::from(input.timestamp)) { tracing::info!("found Ecotone activation block; Upgrade transactions added"); let mut ecotone_upgrade_txs = get_ecotone_upgrade_transactions(); diff --git a/src/derive/stages/batches.rs b/src/derive/stages/batches.rs index 7ec227e..35c674a 100644 --- a/src/derive/stages/batches.rs +++ b/src/derive/stages/batches.rs @@ -3,6 +3,7 @@ use std::cmp::Ordering; use std::collections::BTreeMap; use std::io::Read; use std::sync::{Arc, RwLock}; +use alloy_rlp::Decodable; use ethers::utils::rlp::Rlp; use eyre::Result; @@ -204,13 +205,17 @@ where } // check that block builds on existing chain - if alloy_primitives::B256::from_slice(batch.parent_hash.as_bytes()) != head.hash { + if batch.parent_hash != head.hash { tracing::warn!("invalid parent hash"); return BatchStatus::Drop; } // check the inclusion delay - if batch.epoch_num + self.config.chain.seq_window_size < batch.l1_inclusion_block { + if batch.l1_inclusion_block.is_none() { + tracing::warn!("missing inclusion block"); + return BatchStatus::Drop; + } + if batch.epoch_num + self.config.chain.seq_window_size < batch.l1_inclusion_block.unwrap_or(0) { tracing::warn!("inclusion window elapsed"); return BatchStatus::Drop; } @@ -226,7 +231,7 @@ where }; if let Some(batch_origin) = batch_origin { - if alloy_primitives::B256::from_slice(batch.epoch_hash.as_bytes()) != batch_origin.hash + if batch.epoch_hash != batch_origin.hash { tracing::warn!("invalid epoch hash"); return BatchStatus::Drop; @@ -434,7 +439,8 @@ fn decode_batches(channel: &Channel, chain_id: u64) -> Result> { let rlp = Rlp::new(batch_content); let size = rlp.payload_info()?.total(); - let batch = SingleBatch::decode(&rlp, channel.l1_inclusion_block)?; + let mut batch = SingleBatch::decode(&mut batch_content)?; + batch.l1_inclusion_block = Some(channel.l1_inclusion_block); batches.push(Batch::Single(batch)); offset += size + batch_info.header_len + 1; diff --git a/src/derive/stages/single_batch.rs b/src/derive/stages/single_batch.rs index bb6baea..d613b26 100644 --- a/src/derive/stages/single_batch.rs +++ b/src/derive/stages/single_batch.rs @@ -1,48 +1,29 @@ -use ethers::{ - types::H256, - utils::rlp::{DecoderError, Rlp}, -}; +use alloy_primitives::B256; +use alloy_rlp::{RlpDecodable, RlpEncodable}; use crate::common::RawTransaction; use super::block_input::BlockInput; /// Represents a single batch: a single encoded L2 block -#[derive(Debug, Clone)] +#[derive(Debug, RlpEncodable, RlpDecodable, Clone)] +#[rlp(trailing)] pub struct SingleBatch { /// Block hash of the previous L2 block - pub parent_hash: H256, + pub parent_hash: B256, /// The batch epoch number. Same as the first L1 block number in the epoch. pub epoch_num: u64, /// The block hash of the first L1 block in the epoch - pub epoch_hash: H256, + pub epoch_hash: B256, /// The L2 block timestamp of this batch pub timestamp: u64, /// The L2 block transactions in this batch pub transactions: Vec, /// The L1 block number this batch was fully derived from. - pub l1_inclusion_block: u64, + pub l1_inclusion_block: Option, } impl SingleBatch { - /// Decodes RLP bytes into a [SingleBatch] - pub fn decode(rlp: &Rlp, l1_inclusion_block: u64) -> Result { - let parent_hash = rlp.val_at(0)?; - let epoch_num = rlp.val_at(1)?; - let epoch_hash = rlp.val_at(2)?; - let timestamp = rlp.val_at(3)?; - let transactions = rlp.list_at(4)?; - - Ok(SingleBatch { - parent_hash, - epoch_num, - epoch_hash, - timestamp, - transactions, - l1_inclusion_block, - }) - } - /// If any transactions are empty or deposited transaction types. pub fn has_invalid_transactions(&self) -> bool { self.transactions @@ -56,7 +37,7 @@ impl SingleBatch { timestamp: self.timestamp, epoch: self.epoch_num, transactions: self.transactions.clone(), - l1_inclusion_block: self.l1_inclusion_block, + l1_inclusion_block: self.l1_inclusion_block.unwrap_or(0), } } } diff --git a/src/driver/engine_driver.rs b/src/driver/engine_driver.rs index 97c7292..8881a7f 100644 --- a/src/driver/engine_driver.rs +++ b/src/driver/engine_driver.rs @@ -1,11 +1,10 @@ +//! A module to handle block production & validation + use std::sync::Arc; -use ethers::providers::{Http, Middleware, Provider}; -use ethers::types::Transaction; -use ethers::{ - types::{Block, H256}, - utils::keccak256, -}; +use alloy_primitives::keccak256; +use alloy_rpc_types::{BlockTransactions, Block}; +use alloy_provider::{Provider, ReqwestProvider}; use eyre::Result; use crate::{ @@ -19,7 +18,7 @@ pub struct EngineDriver { /// The L2 execution engine engine: Arc, /// Provider for the local L2 execution RPC - provider: Provider, + provider: ReqwestProvider, /// Blocktime of the L2 chain blocktime: u64, /// Most recent block found on the p2p network @@ -38,7 +37,7 @@ impl EngineDriver { /// Initiates validation & production of a new L2 block from the given [PayloadAttributes] and updates the forkchoice pub async fn handle_attributes(&mut self, attributes: PayloadAttributes) -> Result<()> { let timestamp: u64 = attributes.timestamp.try_into()?; - let block: Option> = self.block_at(timestamp).await; + let block: Option = self.block_at(timestamp).await; if let Some(block) = block { if should_skip(&block, &attributes)? { @@ -117,7 +116,7 @@ impl EngineDriver { async fn skip_attributes( &mut self, attributes: PayloadAttributes, - block: Block, + block: Block, ) -> Result<()> { let new_epoch = *attributes.epoch.as_ref().unwrap(); let new_head = BlockInfo::try_from(block)?; @@ -206,22 +205,22 @@ impl EngineDriver { } /// Fetches the L2 block for a given timestamp from the L2 Execution Client - async fn block_at(&self, timestamp: u64) -> Option> { + async fn block_at(&self, timestamp: u64) -> Option { let time_diff = timestamp as i64 - self.finalized_head.timestamp as i64; let blocks = time_diff / self.blocktime as i64; let block_num = self.finalized_head.number as i64 + blocks; self.provider - .get_block_with_txs(block_num as u64) + .get_block((block_num as u64).into(), true) .await .ok()? } } /// True if transactions in [PayloadAttributes] are not the same as those in a fetched L2 [Block] -fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Result { +fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Result { tracing::debug!( "comparing block at {} with attributes at {}", - block.timestamp, + block.header.timestamp, attributes.timestamp ); @@ -230,11 +229,14 @@ fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Re .as_ref() .unwrap() .iter() - .map(|tx| H256(keccak256(&tx.0))) + .map(|tx| keccak256(&tx.0)) .collect::>(); - let block_hashes = block - .transactions + let BlockTransactions::Full(txs) = &block.transactions else { + return Ok(true); + }; + + let block_hashes = txs .iter() .map(|tx| tx.hash()) .collect::>(); @@ -243,12 +245,11 @@ fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Re tracing::debug!("block hashes: {:?}", block_hashes); let is_same = attributes_hashes == block_hashes - && attributes.timestamp == alloy_primitives::U64::from(block.timestamp.as_u64()) - && attributes.prev_randao - == alloy_primitives::B256::from_slice(block.mix_hash.unwrap().as_bytes()) + && attributes.timestamp == block.header.timestamp + && block.header.mix_hash.map_or(false, |m| m == attributes.prev_randao) && attributes.suggested_fee_recipient - == alloy_primitives::Address::from_slice(block.author.unwrap().as_bytes()) - && attributes.gas_limit == alloy_primitives::U64::from(block.gas_limit.as_u64()); + == block.header.miner + && attributes.gas_limit == block.header.gas_limit; Ok(is_same) } @@ -258,7 +259,7 @@ impl EngineDriver { pub fn new( finalized_head: BlockInfo, finalized_epoch: Epoch, - provider: Provider, + provider: ReqwestProvider, config: &Arc, ) -> Result { let engine = Arc::new(EngineApi::new(&config.l2_engine_url, &config.jwt_secret)); diff --git a/src/driver/info.rs b/src/driver/info.rs index 3696781..d2d7b3b 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -1,8 +1,11 @@ +//! A module to handle fetching blocks. + use crate::config::Config; use crate::driver::types::HeadInfo; -use ethers::middleware::Middleware; -use ethers::providers::{JsonRpcClient, Provider, ProviderError}; -use ethers::types::{Block, BlockId, BlockNumber, Transaction}; + +use eyre::Result; +use alloy_provider::Provider; +use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag}; /// An asynchronous trait for fetching blocks along with their transactions. #[async_trait::async_trait] @@ -11,30 +14,30 @@ pub trait InnerProvider { async fn get_block_with_txs( &self, block_id: BlockId, - ) -> Result>, ProviderError>; + ) -> Result>; } /// Wrapper around a [Provider] -pub struct HeadInfoFetcher<'a, P: JsonRpcClient> { +pub struct HeadInfoFetcher<'a, P: Provider> { /// An ethers [Provider] implementing the [JsonRpcClient] trait - inner: &'a Provider

, + inner: &'a P, } -impl<'a, P: JsonRpcClient> From<&'a Provider

> for HeadInfoFetcher<'a, P> { +impl<'a, P: Provider> From<&'a P> for HeadInfoFetcher<'a, P> { /// Converts a [Provider] to a [HeadInfoFetcher] - fn from(inner: &'a Provider

) -> Self { + fn from(inner: &'a P) -> Self { Self { inner } } } #[async_trait::async_trait] -impl<'a, P: JsonRpcClient> InnerProvider for HeadInfoFetcher<'a, P> { +impl<'a, P: Provider> InnerProvider for HeadInfoFetcher<'a, P> { /// Fetches a block with transactions async fn get_block_with_txs( &self, block_id: BlockId, - ) -> Result>, ProviderError> { - self.inner.get_block_with_txs(block_id).await + ) -> Result> { + self.inner.get_block(block_id, true).await.map_err(Into::into) } } @@ -45,7 +48,7 @@ impl HeadInfoQuery { /// Fetches the latest finalized L2 block pub async fn get_head_info(p: &P, config: &Config) -> HeadInfo { let parsed_head_info = match p - .get_block_with_txs(BlockId::Number(BlockNumber::Finalized)) + .get_block_with_txs(BlockId::Number(BlockNumberOrTag::Finalized)) .await { Ok(Some(block)) => match HeadInfo::try_from_l2_block(config, block) { @@ -82,10 +85,10 @@ mod test_utils { use alloy_primitives::b256; pub struct MockProvider { - pub block: Option>, + pub block: Option, } - pub fn mock_provider(block: Option>) -> MockProvider { + pub fn mock_provider(block: Option) -> MockProvider { MockProvider { block } } @@ -108,7 +111,7 @@ mod test_utils { } } - pub fn valid_block() -> Option> { + pub fn valid_block() -> Option { let raw_block = r#"{ "hash": "0x2e4f4aff36bb7951be9742ad349fb1db84643c6bbac5014f3d196fd88fe333eb", "parentHash": "0xeccf4c06ad0d27be1cadee5720a509d31a9de0462b52f2cf6045d9a73c9aa504", @@ -157,7 +160,7 @@ mod test_utils { async fn get_block_with_txs( &self, _: BlockId, - ) -> Result>, ProviderError> { + ) -> Result> { Ok(self.block.clone()) } } diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 2a02ebf..7328df2 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -1,421 +1,13 @@ -use std::{ - process, - sync::{mpsc::Receiver, Arc, RwLock}, - time::Duration, -}; +//! Contains Drivers for interfacing with the rollup node. -use alloy_primitives::Address; -use ethers::providers::{Http, Provider}; -use eyre::Result; -use reqwest::Url; -use tokio::{ - sync::watch::{self, Sender}, - time::sleep, -}; +pub mod node_driver; +pub use node_driver::NodeDriver; -use crate::{ - common::{BlockInfo, Epoch}, - config::Config, - derive::{state::State, Pipeline}, - engine::{Engine, EngineApi, ExecutionPayload}, - l1::{BlockUpdate, ChainWatcher}, - network::{handlers::block_handler::BlockHandler, service::Service}, - rpc, - telemetry::metrics, -}; +pub mod engine_driver; +pub use engine_driver::EngineDriver; -use self::engine_driver::EngineDriver; +pub mod info; +pub use info::{InnerProvider, HeadInfoFetcher, HeadInfoQuery}; -/// A module to handle block production & validation -mod engine_driver; - -/// A module to handle fetching blocks -mod info; - -/// A module to handle conversions to a [HeadInfo] struct -mod types; -pub use types::*; - -/// Driver is responsible for advancing the execution node by feeding -/// the derived chain into the engine API -pub struct Driver { - /// The derivation pipeline - pipeline: Pipeline, - /// The engine driver - engine_driver: EngineDriver, - /// List of unfinalized L2 blocks with their epochs, L1 inclusions, and sequence numbers - unfinalized_blocks: Vec<(BlockInfo, Epoch, u64, u64)>, - /// Current finalized L1 block number - finalized_l1_block_number: u64, - /// List of unsafe blocks that have not been applied yet - future_unsafe_blocks: Vec, - /// State struct to keep track of global state - state: Arc>, - /// L1 chain watcher - chain_watcher: ChainWatcher, - /// Channel to receive the shutdown signal from - shutdown_recv: watch::Receiver, - /// Channel to receive unsafe blocks from - unsafe_block_recv: Receiver, - /// Channel to send unsafe signer updates to block handler - unsafe_block_signer_sender: Sender

, - /// Networking service - network_service: Option, - /// Channel timeout length - channel_timeout: u64, -} - -impl Driver { - /// Creates a new [Driver] from the given [Config] - pub async fn from_config(config: Config, shutdown_recv: watch::Receiver) -> Result { - let client = reqwest::ClientBuilder::new() - .timeout(Duration::from_secs(5)) - .build()?; - - let http = Http::new_with_client(Url::parse(&config.l2_rpc_url)?, client); - let provider = Provider::new(http); - - let head = - info::HeadInfoQuery::get_head_info(&info::HeadInfoFetcher::from(&provider), &config) - .await; - - let finalized_head = head.l2_block_info; - let finalized_epoch = head.l1_epoch; - let finalized_seq = head.sequence_number; - - tracing::info!("starting from head: {:?}", finalized_head.hash); - - let l1_start_block = - get_l1_start_block(finalized_epoch.number, config.chain.channel_timeout); - - let config = Arc::new(config); - let chain_watcher = - ChainWatcher::new(l1_start_block, finalized_head.number, config.clone())?; - - let state = State::new(finalized_head, finalized_epoch, &provider, config.clone()).await; - let state = Arc::new(RwLock::new(state)); - - let engine_driver = EngineDriver::new(finalized_head, finalized_epoch, provider, &config)?; - let pipeline = Pipeline::new(state.clone(), config.clone(), finalized_seq)?; - - let _addr = rpc::run_server(config.clone()).await?; - - let signer = config.chain.system_config.unsafe_block_signer; - let (unsafe_block_signer_sender, unsafe_block_signer_recv) = watch::channel(signer); - - let (block_handler, unsafe_block_recv) = - BlockHandler::new(config.chain.l2_chain_id, unsafe_block_signer_recv); - - let service = Service::new("0.0.0.0:9876".parse()?, config.chain.l2_chain_id) - .add_handler(Box::new(block_handler)); - - Ok(Self { - engine_driver, - pipeline, - unfinalized_blocks: Vec::new(), - finalized_l1_block_number: 0, - future_unsafe_blocks: Vec::new(), - state, - chain_watcher, - shutdown_recv, - unsafe_block_recv, - unsafe_block_signer_sender, - network_service: Some(service), - channel_timeout: config.chain.channel_timeout, - }) - } -} - -impl Driver { - /// Runs the Driver - pub async fn start(&mut self) -> Result<()> { - self.await_engine_ready().await; - self.chain_watcher.start()?; - - loop { - self.check_shutdown().await; - - if let Err(err) = self.advance().await { - tracing::error!("fatal error: {:?}", err); - self.shutdown().await; - } - } - } - - /// Shuts down the driver - pub async fn shutdown(&self) { - process::exit(0); - } - - /// Checks for shutdown signal and shuts down if received - async fn check_shutdown(&self) { - if *self.shutdown_recv.borrow() { - self.shutdown().await; - } - } - - /// Loops until the [EngineApi] is online and receives a response from the engine. - async fn await_engine_ready(&self) { - while !self.engine_driver.engine_ready().await { - self.check_shutdown().await; - sleep(Duration::from_secs(1)).await; - } - } - - /// Attempts to advance the execution node forward using either L1 info or - /// blocks received on the p2p network. - async fn advance(&mut self) -> Result<()> { - self.advance_safe_head().await?; - self.advance_unsafe_head().await?; - - self.update_finalized(); - self.update_metrics(); - self.try_start_networking()?; - - Ok(()) - } - - /// Attempts to advance the execution node forward one L1 block using derived - /// L1 data. Errors if the most recent PayloadAttributes from the pipeline - /// does not successfully advance the node - async fn advance_safe_head(&mut self) -> Result<()> { - self.handle_next_block_update().await?; - self.update_state_head()?; - - for next_attributes in self.pipeline.by_ref() { - let l1_inclusion_block = next_attributes - .l1_inclusion_block - .ok_or(eyre::eyre!("attributes without inclusion block"))?; - - let seq_number = next_attributes - .seq_number - .ok_or(eyre::eyre!("attributes without seq number"))?; - - self.engine_driver - .handle_attributes(next_attributes) - .await - .map_err(|e| eyre::eyre!("failed to handle attributes: {}", e))?; - - tracing::info!( - "safe head updated: {} {:?}", - self.engine_driver.safe_head.number, - self.engine_driver.safe_head.hash, - ); - - let new_safe_head = self.engine_driver.safe_head; - let new_safe_epoch = self.engine_driver.safe_epoch; - - self.state - .write() - .map_err(|_| eyre::eyre!("lock poisoned"))? - .update_safe_head(new_safe_head, new_safe_epoch); - - let unfinalized_entry = ( - new_safe_head, - new_safe_epoch, - l1_inclusion_block, - seq_number, - ); - - self.unfinalized_blocks.push(unfinalized_entry); - } - - Ok(()) - } - - /// Collects unsafe blocks received via p2p gossip and updates the forkchoice with the first available unsafe block. - async fn advance_unsafe_head(&mut self) -> Result<()> { - while let Ok(payload) = self.unsafe_block_recv.try_recv() { - self.future_unsafe_blocks.push(payload); - } - - self.future_unsafe_blocks.retain(|payload| { - let unsafe_block_num: u64 = match payload.block_number.try_into() { - Ok(num) => num, - Err(_) => return false, - }; - let synced_block_num = self.engine_driver.unsafe_head.number; - - unsafe_block_num > synced_block_num && unsafe_block_num - synced_block_num < 1024 - }); - - let next_unsafe_payload = self - .future_unsafe_blocks - .iter() - .find(|p| p.parent_hash == self.engine_driver.unsafe_head.hash); - - if let Some(payload) = next_unsafe_payload { - _ = self.engine_driver.handle_unsafe_payload(payload).await; - } - - Ok(()) - } - - /// Updates the [State] `safe_head` - fn update_state_head(&self) -> Result<()> { - let mut state = self - .state - .write() - .map_err(|_| eyre::eyre!("lock poisoned"))?; - - state.update_safe_head(self.engine_driver.safe_head, self.engine_driver.safe_epoch); - - Ok(()) - } - - /// Ingests the next update from the block update channel - async fn handle_next_block_update(&mut self) -> Result<()> { - let next = self.chain_watcher.try_recv_from_channel(); - - if let Ok(update) = next { - match update { - BlockUpdate::NewBlock(l1_info) => { - let num = l1_info.block_info.number; - - let signer = - Address::from_slice(l1_info.system_config.unsafe_block_signer.as_slice()); - self.unsafe_block_signer_sender.send(signer)?; - - self.pipeline.push_batcher_transactions( - // cloning `bytes::Bytes` is cheap - l1_info.batcher_transactions.clone(), - num, - )?; - - self.state - .write() - .map_err(|_| eyre::eyre!("lock poisoned"))? - .update_l1_info(*l1_info); - } - BlockUpdate::Reorg => { - tracing::warn!("reorg detected, purging pipeline"); - - self.unfinalized_blocks.clear(); - - let l1_start_block = get_l1_start_block( - self.engine_driver.finalized_epoch.number, - self.channel_timeout, - ); - - self.chain_watcher - .restart(l1_start_block, self.engine_driver.finalized_head.number)?; - - self.state - .write() - .map_err(|_| eyre::eyre!("lock poisoned"))? - .purge( - self.engine_driver.finalized_head, - self.engine_driver.finalized_epoch, - ); - - self.pipeline.purge()?; - self.engine_driver.reorg(); - } - BlockUpdate::FinalityUpdate(num) => { - self.finalized_l1_block_number = num; - } - } - } - - Ok(()) - } - - /// Updates the current finalized L2 block in the [EngineDriver] based on their inclusion in finalized L1 blocks - fn update_finalized(&mut self) { - let new_finalized = self - .unfinalized_blocks - .iter() - .filter(|(_, _, inclusion, seq)| { - *inclusion <= self.finalized_l1_block_number && *seq == 0 - }) - .last(); - - if let Some((head, epoch, _, _)) = new_finalized { - self.engine_driver.update_finalized(*head, *epoch); - } - - self.unfinalized_blocks - .retain(|(_, _, inclusion, _)| *inclusion > self.finalized_l1_block_number); - } - - /// Begins p2p networking if fully synced with no unfinalized blocks - fn try_start_networking(&mut self) -> Result<()> { - if self.synced() { - if let Some(service) = self.network_service.take() { - service.start()?; - } - } - - Ok(()) - } - - /// Updates Prometheus metrics - fn update_metrics(&self) { - metrics::FINALIZED_HEAD.set(self.engine_driver.finalized_head.number as i64); - metrics::SAFE_HEAD.set(self.engine_driver.safe_head.number as i64); - metrics::SYNCED.set(self.synced() as i64); - } - - /// True if there are no unfinalized blocks - fn synced(&self) -> bool { - !self.unfinalized_blocks.is_empty() - } -} - -/// Retrieves the L1 start block number. -/// If an overflow occurs during subtraction, the function returns the genesis block #0. -fn get_l1_start_block(epoch_number: u64, channel_timeout: u64) -> u64 { - epoch_number.saturating_sub(channel_timeout) -} - -#[cfg(test)] -mod tests { - use std::{path::PathBuf, str::FromStr}; - - use ethers::{ - providers::{Http, Middleware}, - types::{BlockId, BlockNumber}, - }; - use eyre::Result; - use tokio::sync::watch::channel; - - use crate::config::{ChainConfig, CliConfig}; - - use super::*; - - #[tokio::test] - async fn test_new_driver_from_finalized_head() -> Result<()> { - if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() { - let config_path = PathBuf::from_str("config.toml")?; - let rpc = std::env::var("L1_TEST_RPC_URL")?; - let l2_rpc = std::env::var("L2_TEST_RPC_URL")?; - let cli_config = CliConfig { - l1_rpc_url: Some(rpc.to_owned()), - l1_beacon_url: None, - l2_rpc_url: Some(l2_rpc.to_owned()), - l2_engine_url: None, - jwt_secret: Some( - "d195a64e08587a3f1560686448867220c2727550ce3e0c95c7200d0ade0f9167".to_owned(), - ), - checkpoint_sync_url: Some(l2_rpc.to_owned()), - rpc_port: None, - rpc_addr: None, - devnet: false, - }; - let config = Config::new(&config_path, cli_config, ChainConfig::optimism_goerli()); - let (_shutdown_sender, shutdown_recv) = channel(false); - - let block_id = BlockId::Number(BlockNumber::Finalized); - let provider = Provider::::try_from(config.l2_rpc_url.clone())?; - let finalized_block = provider.get_block(block_id).await?.unwrap(); - - let driver = Driver::from_config(config, shutdown_recv).await?; - - assert_eq!( - driver.engine_driver.finalized_head.number, - finalized_block.number.unwrap().as_u64() - ); - } - Ok(()) - } -} +pub mod types; +pub use types::HeadInfo; diff --git a/src/driver/node_driver.rs b/src/driver/node_driver.rs new file mode 100644 index 0000000..dcba681 --- /dev/null +++ b/src/driver/node_driver.rs @@ -0,0 +1,408 @@ +//! The node driver module contains the logic for advancing the execution node +//! by feeding the derived chain into the Engine API. + +use std::{ + process, + sync::{mpsc::Receiver, Arc, RwLock}, + time::Duration, +}; + +use alloy_primitives::Address; +use alloy_provider::{ProviderBuilder, Provider}; +use eyre::Result; +use reqwest::Url; +use tokio::{ + sync::watch::{self, Sender}, + time::sleep, +}; + +use crate::{ + common::{BlockInfo, Epoch}, + config::Config, + derive::{state::State, Pipeline}, + engine::{Engine, EngineApi, ExecutionPayload}, + l1::{BlockUpdate, ChainWatcher}, + network::{handlers::block_handler::BlockHandler, service::Service}, + rpc, + telemetry::metrics, +}; + +use crate::driver::{HeadInfoFetcher, HeadInfoQuery, EngineDriver}; + +/// NodeDriver is responsible for advancing the execution node by feeding +/// the derived chain into the engine API +pub struct NodeDriver { + /// The derivation pipeline + pipeline: Pipeline, + /// The engine driver + engine_driver: EngineDriver, + /// List of unfinalized L2 blocks with their epochs, L1 inclusions, and sequence numbers + unfinalized_blocks: Vec<(BlockInfo, Epoch, u64, u64)>, + /// Current finalized L1 block number + finalized_l1_block_number: u64, + /// List of unsafe blocks that have not been applied yet + future_unsafe_blocks: Vec, + /// State struct to keep track of global state + state: Arc>, + /// L1 chain watcher + chain_watcher: ChainWatcher, + /// Channel to receive the shutdown signal from + shutdown_recv: watch::Receiver, + /// Channel to receive unsafe blocks from + unsafe_block_recv: Receiver, + /// Channel to send unsafe signer updates to block handler + unsafe_block_signer_sender: Sender
, + /// Networking service + network_service: Option, + /// Channel timeout length + channel_timeout: u64, +} + +impl NodeDriver { + /// Creates a new [Driver] from the given [Config] + pub async fn from_config(config: Config, shutdown_recv: watch::Receiver) -> Result { + let url = Url::parse(&config.l2_rpc_url)?; + let provider = ProviderBuilder::new().on_http(url); + + let head = + HeadInfoQuery::get_head_info(&HeadInfoFetcher::from(&provider), &config) + .await; + + let finalized_head = head.l2_block_info; + let finalized_epoch = head.l1_epoch; + let finalized_seq = head.sequence_number; + + tracing::info!("starting from head: {:?}", finalized_head.hash); + + let l1_start_block = + get_l1_start_block(finalized_epoch.number, config.chain.channel_timeout); + + let config = Arc::new(config); + let chain_watcher = + ChainWatcher::new(l1_start_block, finalized_head.number, config.clone())?; + + let state = State::new(finalized_head, finalized_epoch, &provider, config.clone()).await; + let state = Arc::new(RwLock::new(state)); + + let engine_driver = EngineDriver::new(finalized_head, finalized_epoch, provider, &config)?; + let pipeline = Pipeline::new(state.clone(), config.clone(), finalized_seq)?; + + let _addr = rpc::run_server(config.clone()).await?; + + let signer = config.chain.system_config.unsafe_block_signer; + let (unsafe_block_signer_sender, unsafe_block_signer_recv) = watch::channel(signer); + + let (block_handler, unsafe_block_recv) = + BlockHandler::new(config.chain.l2_chain_id, unsafe_block_signer_recv); + + let service = Service::new("0.0.0.0:9876".parse()?, config.chain.l2_chain_id) + .add_handler(Box::new(block_handler)); + + Ok(Self { + engine_driver, + pipeline, + unfinalized_blocks: Vec::new(), + finalized_l1_block_number: 0, + future_unsafe_blocks: Vec::new(), + state, + chain_watcher, + shutdown_recv, + unsafe_block_recv, + unsafe_block_signer_sender, + network_service: Some(service), + channel_timeout: config.chain.channel_timeout, + }) + } +} + +impl NodeDriver { + /// Runs the Driver + pub async fn start(&mut self) -> Result<()> { + self.await_engine_ready().await; + self.chain_watcher.start()?; + + loop { + self.check_shutdown().await; + + if let Err(err) = self.advance().await { + tracing::error!("fatal error: {:?}", err); + self.shutdown().await; + } + } + } + + /// Shuts down the driver + pub async fn shutdown(&self) { + process::exit(0); + } + + /// Checks for shutdown signal and shuts down if received + async fn check_shutdown(&self) { + if *self.shutdown_recv.borrow() { + self.shutdown().await; + } + } + + /// Loops until the [EngineApi] is online and receives a response from the engine. + async fn await_engine_ready(&self) { + while !self.engine_driver.engine_ready().await { + self.check_shutdown().await; + sleep(Duration::from_secs(1)).await; + } + } + + /// Attempts to advance the execution node forward using either L1 info or + /// blocks received on the p2p network. + async fn advance(&mut self) -> Result<()> { + self.advance_safe_head().await?; + self.advance_unsafe_head().await?; + + self.update_finalized(); + self.update_metrics(); + self.try_start_networking()?; + + Ok(()) + } + + /// Attempts to advance the execution node forward one L1 block using derived + /// L1 data. Errors if the most recent PayloadAttributes from the pipeline + /// does not successfully advance the node + async fn advance_safe_head(&mut self) -> Result<()> { + self.handle_next_block_update().await?; + self.update_state_head()?; + + for next_attributes in self.pipeline.by_ref() { + let l1_inclusion_block = next_attributes + .l1_inclusion_block + .ok_or(eyre::eyre!("attributes without inclusion block"))?; + + let seq_number = next_attributes + .seq_number + .ok_or(eyre::eyre!("attributes without seq number"))?; + + self.engine_driver + .handle_attributes(next_attributes) + .await + .map_err(|e| eyre::eyre!("failed to handle attributes: {}", e))?; + + tracing::info!( + "safe head updated: {} {:?}", + self.engine_driver.safe_head.number, + self.engine_driver.safe_head.hash, + ); + + let new_safe_head = self.engine_driver.safe_head; + let new_safe_epoch = self.engine_driver.safe_epoch; + + self.state + .write() + .map_err(|_| eyre::eyre!("lock poisoned"))? + .update_safe_head(new_safe_head, new_safe_epoch); + + let unfinalized_entry = ( + new_safe_head, + new_safe_epoch, + l1_inclusion_block, + seq_number, + ); + + self.unfinalized_blocks.push(unfinalized_entry); + } + + Ok(()) + } + + /// Collects unsafe blocks received via p2p gossip and updates the forkchoice with the first available unsafe block. + async fn advance_unsafe_head(&mut self) -> Result<()> { + while let Ok(payload) = self.unsafe_block_recv.try_recv() { + self.future_unsafe_blocks.push(payload); + } + + self.future_unsafe_blocks.retain(|payload| { + let unsafe_block_num: u64 = match payload.block_number.try_into() { + Ok(num) => num, + Err(_) => return false, + }; + let synced_block_num = self.engine_driver.unsafe_head.number; + + unsafe_block_num > synced_block_num && unsafe_block_num - synced_block_num < 1024 + }); + + let next_unsafe_payload = self + .future_unsafe_blocks + .iter() + .find(|p| p.parent_hash == self.engine_driver.unsafe_head.hash); + + if let Some(payload) = next_unsafe_payload { + _ = self.engine_driver.handle_unsafe_payload(payload).await; + } + + Ok(()) + } + + /// Updates the [State] `safe_head` + fn update_state_head(&self) -> Result<()> { + let mut state = self + .state + .write() + .map_err(|_| eyre::eyre!("lock poisoned"))?; + + state.update_safe_head(self.engine_driver.safe_head, self.engine_driver.safe_epoch); + + Ok(()) + } + + /// Ingests the next update from the block update channel + async fn handle_next_block_update(&mut self) -> Result<()> { + let next = self.chain_watcher.try_recv_from_channel(); + + if let Ok(update) = next { + match update { + BlockUpdate::NewBlock(l1_info) => { + let num = l1_info.block_info.number; + + let signer = + Address::from_slice(l1_info.system_config.unsafe_block_signer.as_slice()); + self.unsafe_block_signer_sender.send(signer)?; + + self.pipeline.push_batcher_transactions( + // cloning `bytes::Bytes` is cheap + l1_info.batcher_transactions.clone(), + num, + )?; + + self.state + .write() + .map_err(|_| eyre::eyre!("lock poisoned"))? + .update_l1_info(*l1_info); + } + BlockUpdate::Reorg => { + tracing::warn!("reorg detected, purging pipeline"); + + self.unfinalized_blocks.clear(); + + let l1_start_block = get_l1_start_block( + self.engine_driver.finalized_epoch.number, + self.channel_timeout, + ); + + self.chain_watcher + .restart(l1_start_block, self.engine_driver.finalized_head.number)?; + + self.state + .write() + .map_err(|_| eyre::eyre!("lock poisoned"))? + .purge( + self.engine_driver.finalized_head, + self.engine_driver.finalized_epoch, + ); + + self.pipeline.purge()?; + self.engine_driver.reorg(); + } + BlockUpdate::FinalityUpdate(num) => { + self.finalized_l1_block_number = num; + } + } + } + + Ok(()) + } + + /// Updates the current finalized L2 block in the [EngineDriver] based on their inclusion in finalized L1 blocks + fn update_finalized(&mut self) { + let new_finalized = self + .unfinalized_blocks + .iter() + .filter(|(_, _, inclusion, seq)| { + *inclusion <= self.finalized_l1_block_number && *seq == 0 + }) + .last(); + + if let Some((head, epoch, _, _)) = new_finalized { + self.engine_driver.update_finalized(*head, *epoch); + } + + self.unfinalized_blocks + .retain(|(_, _, inclusion, _)| *inclusion > self.finalized_l1_block_number); + } + + /// Begins p2p networking if fully synced with no unfinalized blocks + fn try_start_networking(&mut self) -> Result<()> { + if self.synced() { + if let Some(service) = self.network_service.take() { + service.start()?; + } + } + + Ok(()) + } + + /// Updates Prometheus metrics + fn update_metrics(&self) { + metrics::FINALIZED_HEAD.set(self.engine_driver.finalized_head.number as i64); + metrics::SAFE_HEAD.set(self.engine_driver.safe_head.number as i64); + metrics::SYNCED.set(self.synced() as i64); + } + + /// True if there are no unfinalized blocks + fn synced(&self) -> bool { + !self.unfinalized_blocks.is_empty() + } +} + +/// Retrieves the L1 start block number. +/// If an overflow occurs during subtraction, the function returns the genesis block #0. +fn get_l1_start_block(epoch_number: u64, channel_timeout: u64) -> u64 { + epoch_number.saturating_sub(channel_timeout) +} + +#[cfg(test)] +mod tests { + use std::{path::PathBuf, str::FromStr}; + + use alloy_rpc_types::{BlockId, BlockNumberOrTag}; + use eyre::Result; + use tokio::sync::watch::channel; + + use crate::config::{ChainConfig, CliConfig}; + + use super::*; + + #[tokio::test] + async fn test_new_driver_from_finalized_head() -> Result<()> { + if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() { + let config_path = PathBuf::from_str("config.toml")?; + let rpc = std::env::var("L1_TEST_RPC_URL")?; + let l2_rpc = std::env::var("L2_TEST_RPC_URL")?; + let cli_config = CliConfig { + l1_rpc_url: Some(rpc.to_owned()), + l1_beacon_url: None, + l2_rpc_url: Some(l2_rpc.to_owned()), + l2_engine_url: None, + jwt_secret: Some( + "d195a64e08587a3f1560686448867220c2727550ce3e0c95c7200d0ade0f9167".to_owned(), + ), + checkpoint_sync_url: Some(l2_rpc.to_owned()), + rpc_port: None, + rpc_addr: None, + devnet: false, + }; + let config = Config::new(&config_path, cli_config, ChainConfig::optimism_goerli()); + let (_shutdown_sender, shutdown_recv) = channel(false); + + let block_id = BlockId::Number(BlockNumberOrTag::Finalized); + let url = Url::parse(&config.l2_rpc_url)?; + let provider = ProviderBuilder::new().on_http(url); + let finalized_block = provider.get_block(block_id, true).await?.unwrap(); + + let driver = NodeDriver::from_config(config, shutdown_recv).await?; + + assert_eq!( + driver.engine_driver.finalized_head.number, + finalized_block.header.number.unwrap() + ); + } + Ok(()) + } +} diff --git a/src/driver/types.rs b/src/driver/types.rs index 9fc2f70..5ba471c 100644 --- a/src/driver/types.rs +++ b/src/driver/types.rs @@ -1,5 +1,7 @@ -use ethers::types::{Block, Transaction}; +//! A module to handle conversions to a [HeadInfo] struct. + use eyre::Result; +use alloy_rpc_types::{BlockTransactions, Block}; use serde::{Deserialize, Serialize}; use crate::{ @@ -22,10 +24,10 @@ impl HeadInfo { /// Returns the head info from the given L2 block and the system config. /// The config is used to check whether the block is subject to the Ecotone hardfork /// (which changes the way the head info is constructed from the block). - pub fn try_from_l2_block(config: &Config, l2_block: Block) -> Result { + pub fn try_from_l2_block(config: &Config, l2_block: Block) -> Result { if config .chain - .is_ecotone_but_not_first_block(l2_block.timestamp.as_u64()) + .is_ecotone_but_not_first_block(l2_block.header.timestamp) { HeadInfo::try_from_ecotone_block(l2_block) } else { @@ -35,8 +37,13 @@ impl HeadInfo { /// Returns `HeadInfo` consisting of the L2 block, the L1 epoch block it belongs to, and the L2 block's position in the epoch. /// This function is used when the L2 block is from the Bedrock hardfork or earlier. - fn try_from_bedrock_block(block: Block) -> Result { - let Some(first_tx) = block.transactions.first() else { + pub fn try_from_bedrock_block(block: Block) -> Result { + let BlockTransactions::Full(txs) = block.transactions else { + return Err(eyre::eyre!( + "Could not find the L1 attributes deposited transaction" + )); + }; + let Some(first_tx) = txs.first() else { return Err(eyre::eyre!( "Could not find the L1 attributes deposited transaction" )); @@ -54,8 +61,13 @@ impl HeadInfo { /// Returns `HeadInfo` consisting of the L2 block, the L1 epoch block it belongs to, and the L2 block's position in the epoch. /// This function is used when the L2 block is from the Ecotone hardfork or later. - fn try_from_ecotone_block(block: Block) -> Result { - let Some(first_tx) = block.transactions.first() else { + pub fn try_from_ecotone_block(block: Block) -> Result { + let BlockTransactions::Full(txs) = block.transactions else { + return Err(eyre::eyre!( + "Could not find the L1 attributes deposited transaction" + )); + }; + let Some(first_tx) = txs.first() else { return Err(eyre::eyre!( "Could not find the L1 attributes deposited transaction" )); @@ -76,14 +88,10 @@ impl HeadInfo { mod tests { mod head_info_bedrock { use crate::driver::HeadInfo; - use std::str::FromStr; - - use alloy_primitives::b256; - use ethers::{ - providers::{Middleware, Provider}, - types::{Block, Transaction, H256}, - }; use eyre::Result; + use alloy_provider::{Provider, ProviderBuilder}; + use alloy_primitives::b256; + use alloy_rpc_types::Block; #[test] fn should_fail_conversion_from_a_block_to_head_info_if_missing_l1_deposited_tx( @@ -115,13 +123,9 @@ mod tests { } "#; - let block: Block = serde_json::from_str(raw_block)?; + let block: Block = serde_json::from_str(raw_block)?; - // Act let head = HeadInfo::try_from_bedrock_block(block); - - // Assert - assert!(head.is_err()); let err = head.unwrap_err(); assert!(err @@ -180,7 +184,7 @@ mod tests { } "#; - let block: Block = serde_json::from_str(raw_block)?; + let block: Block = serde_json::from_str(raw_block)?; let expected_l2_block_hash = b256!("2e4f4aff36bb7951be9742ad349fb1db84643c6bbac5014f3d196fd88fe333eb"); @@ -192,10 +196,8 @@ mod tests { let expected_l1_epoch_block_number = 8874020; let expected_l1_epoch_timestamp = 1682191440; - // Act let head = HeadInfo::try_from_bedrock_block(block); - // Assert assert!(head.is_ok()); let HeadInfo { l2_block_info, @@ -218,41 +220,43 @@ mod tests { #[tokio::test] async fn test_head_info_from_l2_block_hash() -> Result<()> { - if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() - { - let l2_block_hash = H256::from_str( - "75d4a658d7b6430c874c5518752a8d90fb1503eccd6ae4cfc97fd4aedeebb939", - )?; + let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { + eyre::bail!("L1_TEST_RPC_URL is not set"); + }; + let Ok(l2_rpc_url) = std::env::var("L2_TEST_RPC_URL") else { + eyre::bail!("L2_TEST_RPC_URL is not set"); + }; - let expected_l2_block_number = 8428108; - let expected_l2_block_timestamp = 1682284284; + let l2_block_hash = b256!("75d4a658d7b6430c874c5518752a8d90fb1503eccd6ae4cfc97fd4aedeebb939"); - let expected_l1_epoch_hash = - b256!("76ab90dc2afea158bbe14a99f22d5f867b51719378aa37d1a3aa3833ace67cad"); - let expected_l1_epoch_block_number = 8879997; - let expected_l1_epoch_timestamp = 1682284164; + let expected_l2_block_number = 8428108; + let expected_l2_block_timestamp = 1682284284; + + let expected_l1_epoch_hash = + b256!("76ab90dc2afea158bbe14a99f22d5f867b51719378aa37d1a3aa3833ace67cad"); + let expected_l1_epoch_block_number = 8879997; + let expected_l1_epoch_timestamp = 1682284164; - let l2_rpc = std::env::var("L2_TEST_RPC_URL")?; - let provider = Provider::try_from(l2_rpc)?; + let l2_rpc_url = reqwest::Url::parse(&l2_rpc_url)?; + let l2_provider = ProviderBuilder::new().on_http(l2_rpc_url); - let l2_block = provider.get_block_with_txs(l2_block_hash).await?.unwrap(); - let head = HeadInfo::try_from_bedrock_block(l2_block)?; + let l2_block = l2_provider.get_block(l2_block_hash.into(), true).await?.unwrap(); + let head = HeadInfo::try_from_bedrock_block(l2_block)?; - let HeadInfo { - l2_block_info, - l1_epoch, - sequence_number, - } = head; + let HeadInfo { + l2_block_info, + l1_epoch, + sequence_number, + } = head; - assert_eq!(l2_block_info.number, expected_l2_block_number); - assert_eq!(l2_block_info.timestamp, expected_l2_block_timestamp); + assert_eq!(l2_block_info.number, expected_l2_block_number); + assert_eq!(l2_block_info.timestamp, expected_l2_block_timestamp); - assert_eq!(l1_epoch.hash, expected_l1_epoch_hash); - assert_eq!(l1_epoch.number, expected_l1_epoch_block_number); - assert_eq!(l1_epoch.timestamp, expected_l1_epoch_timestamp); + assert_eq!(l1_epoch.hash, expected_l1_epoch_hash); + assert_eq!(l1_epoch.number, expected_l1_epoch_block_number); + assert_eq!(l1_epoch.timestamp, expected_l1_epoch_timestamp); - assert_eq!(sequence_number, 4); - } + assert_eq!(sequence_number, 4); Ok(()) } @@ -260,52 +264,49 @@ mod tests { mod head_info_ecotone { use crate::driver::HeadInfo; - use std::str::FromStr; - - use alloy_primitives::b256; - use ethers::{ - providers::{Middleware, Provider}, - types::H256, - }; use eyre::Result; + use alloy_provider::{Provider, ProviderBuilder}; + use alloy_primitives::b256; #[tokio::test] async fn test_head_info_from_l2_block_hash() -> Result<()> { - if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() - { - let l2_block_hash = H256::from_str( - "0xbdd36f0c7ec8e17647dac2780130a842c47dba0025387e80408c161fdb115412", - )?; + let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { + eyre::bail!("L1_TEST_RPC_URL is not set"); + }; + let Ok(l2_rpc_url) = std::env::var("L2_TEST_RPC_URL") else { + eyre::bail!("L2_TEST_RPC_URL is not set"); + }; - let expected_l2_block_number = 21564471; - let expected_l2_block_timestamp = 1708557010; + let l2_block_hash = b256!("bdd36f0c7ec8e17647dac2780130a842c47dba0025387e80408c161fdb115412"); - let expected_l1_epoch_hash = - b256!("231ac984a3fc58757efe373b0b5bff0589c0e67a969a6cbc56ec959739525b31"); - let expected_l1_epoch_block_number = 10575507; - let expected_l1_epoch_timestamp = 1708556928; + let expected_l2_block_number = 21564471; + let expected_l2_block_timestamp = 1708557010; - let l2_rpc = std::env::var("L2_TEST_RPC_URL")?; - let provider = Provider::try_from(l2_rpc)?; + let expected_l1_epoch_hash = + b256!("231ac984a3fc58757efe373b0b5bff0589c0e67a969a6cbc56ec959739525b31"); + let expected_l1_epoch_block_number = 10575507; + let expected_l1_epoch_timestamp = 1708556928; - let l2_block = provider.get_block_with_txs(l2_block_hash).await?.unwrap(); - let head = HeadInfo::try_from_ecotone_block(l2_block)?; + let l2_rpc_url = reqwest::Url::parse(&l2_rpc_url)?; + let l2_provider = ProviderBuilder::new().on_http(l2_rpc_url); - let HeadInfo { - l2_block_info, - l1_epoch, - sequence_number, - } = head; + let l2_block = l2_provider.get_block(l2_block_hash.into(), true).await?.unwrap(); + let head = HeadInfo::try_from_ecotone_block(l2_block)?; - assert_eq!(l2_block_info.number, expected_l2_block_number); - assert_eq!(l2_block_info.timestamp, expected_l2_block_timestamp); + let HeadInfo { + l2_block_info, + l1_epoch, + sequence_number, + } = head; + + assert_eq!(l2_block_info.number, expected_l2_block_number); + assert_eq!(l2_block_info.timestamp, expected_l2_block_timestamp); - assert_eq!(l1_epoch.hash, expected_l1_epoch_hash); - assert_eq!(l1_epoch.number, expected_l1_epoch_block_number); - assert_eq!(l1_epoch.timestamp, expected_l1_epoch_timestamp); + assert_eq!(l1_epoch.hash, expected_l1_epoch_hash); + assert_eq!(l1_epoch.number, expected_l1_epoch_block_number); + assert_eq!(l1_epoch.timestamp, expected_l1_epoch_timestamp); - assert_eq!(sequence_number, 4); - } + assert_eq!(sequence_number, 4); Ok(()) } From bee6d00a9eed74f48727ae2315512b2a67db17e5 Mon Sep 17 00:00:00 2001 From: refcell Date: Wed, 1 May 2024 10:08:03 -0700 Subject: [PATCH 3/5] chore(derive): alloy type ports --- src/config/mod.rs | 10 +- src/derive/ecotone_upgrade.rs | 89 +++++----- src/derive/mod.rs | 201 +--------------------- src/derive/pipeline.rs | 193 +++++++++++++++++++++ src/derive/purgeable.rs | 2 + src/derive/stages/attributes.rs | 95 +++++----- src/derive/stages/batcher_transactions.rs | 7 +- src/derive/stages/batches.rs | 22 +-- src/derive/stages/mod.rs | 8 +- src/derive/state.rs | 35 ++-- src/driver/engine_driver.rs | 21 +-- src/driver/info.rs | 47 +++-- src/driver/mod.rs | 2 +- src/driver/node_driver.rs | 11 +- src/driver/types.rs | 26 ++- src/runner/mod.rs | 4 +- 16 files changed, 394 insertions(+), 379 deletions(-) create mode 100644 src/derive/pipeline.rs diff --git a/src/config/mod.rs b/src/config/mod.rs index 827adcc..a8149cc 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,6 +1,6 @@ use std::{fmt, iter, path::PathBuf, process::exit, str::FromStr}; -use alloy_primitives::{Address, B256, U64, U256}; +use alloy_primitives::{Address, B256, U256, U64}; use figment::{ providers::{Format, Serialized, Toml}, Figment, @@ -293,14 +293,14 @@ impl ChainConfig { } /// Returns true if the block is the first block subject to the Ecotone hardfork - pub fn is_ecotone_activation_block(&self, l2_block_timestamp: U64) -> bool { - l2_block_timestamp == self.ecotone_time + pub fn is_ecotone_activation_block(&self, l2_block_timestamp: impl Into) -> bool { + l2_block_timestamp.into() == U64::from(self.ecotone_time) } /// Returns true if Ecotone hardfork is active but the block is not the /// first block subject to the hardfork. Ecotone activation at genesis does not count. - pub fn is_ecotone_but_not_first_block(&self, l2_block_timestamp: U64) -> bool { - let is_ecotone = l2_block_timestamp >= self.ecotone_time; + pub fn is_ecotone_but_not_first_block(&self, l2_block_timestamp: impl Into) -> bool { + let is_ecotone = l2_block_timestamp.into() >= U64::from(self.ecotone_time); is_ecotone && !self.is_ecotone_activation_block(l2_block_timestamp) } diff --git a/src/derive/ecotone_upgrade.rs b/src/derive/ecotone_upgrade.rs index 766c713..e204e01 100644 --- a/src/derive/ecotone_upgrade.rs +++ b/src/derive/ecotone_upgrade.rs @@ -1,6 +1,9 @@ +//! A module that handles the Ecotone Hardfork Upgrade. + use std::str::FromStr; -use ethers::types::{Address, Bytes, Transaction, H256, U256, U64}; +use alloy_consensus::TxEnvelope; +use alloy_primitives::{Address, b256, address, uint, Bytes, U256, U64}; use crate::common::RawTransaction; @@ -11,17 +14,29 @@ use crate::common::RawTransaction; pub fn get_ecotone_upgrade_transactions() -> Vec { let mut upgrade_transactions = Vec::with_capacity(6); + // Deploy the L1 Block Contract + let mut buffer = Vec::new(); + TxEnvelope::Deposit(TxDeposit { + source_hash: DEPLOY_L1_BLOCK_SOURCE.source_hash(), + from: L1_BLOCK_DEPLOYER_ADDRESS, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 375_000, + is_system_transaction: false, + input: l1_block_deployment_bytecode, + }) + .encode(&mut buffer); + upgrade_transactions.push(RawTransaction::from(buffer)); + let deploy_l1_block = Transaction { transaction_type: Some(U64::from(0x7E)), - source_hash: H256::from_str( - "0x877a6077205782ea15a6dc8699fa5ebcec5e0f4389f09cb8eda09488231346f8", - ) - .unwrap(), - from: Address::from_str("0x4210000000000000000000000000000000000000").unwrap(), + source_hash: b256!("877a6077205782ea15a6dc8699fa5ebcec5e0f4389f09cb8eda09488231346f8"), + from: address!("4210000000000000000000000000000000000000"), to: None, mint: None, - value: U256::from(0), - gas: U256::from(375_000), + value: U256::ZERO(), + gas: uint!(375_000_U256), is_system_tx: false, input: Bytes::from_str("0x608060405234801561001057600080fd5b5061053e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638381f58a11610097578063c598591811610066578063c598591814610229578063e591b28214610249578063e81b2c6d14610289578063f82061401461029257600080fd5b80638381f58a146101e35780638b239f73146101f75780639e8c496614610200578063b80777ea1461020957600080fd5b806354fd4d50116100d357806354fd4d50146101335780635cf249691461017c57806364ca23ef1461018557806368d5dca6146101b257600080fd5b8063015d8eb9146100fa57806309bd5a601461010f578063440a5e201461012b575b600080fd5b61010d61010836600461044c565b61029b565b005b61011860025481565b6040519081526020015b60405180910390f35b61010d6103da565b61016f6040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161012291906104be565b61011860015481565b6003546101999067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610122565b6003546101ce9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610122565b6000546101999067ffffffffffffffff1681565b61011860055481565b61011860065481565b6000546101999068010000000000000000900467ffffffffffffffff1681565b6003546101ce906c01000000000000000000000000900463ffffffff1681565b61026473deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b61011860045481565b61011860075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b3373deaddeaddeaddeaddeaddeaddeaddeaddead00011461040357633cc50b456000526004601cfd5b60043560801c60035560143560801c600055602435600155604435600755606435600255608435600455565b803567ffffffffffffffff8116811461044757600080fd5b919050565b600080600080600080600080610100898b03121561046957600080fd5b6104728961042f565b975061048060208a0161042f565b9650604089013595506060890135945061049c60808a0161042f565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b818110156104eb578581018301518582016040015282016104cf565b818111156104fd576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201604001939250505056fea164736f6c634300080f000a").unwrap(), ..Default::default() @@ -30,15 +45,12 @@ pub fn get_ecotone_upgrade_transactions() -> Vec { let deploy_gas_price_oracle = Transaction { transaction_type: Some(U64::from(0x7E)), - source_hash: H256::from_str( - "0xa312b4510adf943510f05fcc8f15f86995a5066bd83ce11384688ae20e6ecf42", - ) - .unwrap(), - from: Address::from_str("0x4210000000000000000000000000000000000001").unwrap(), + source_hash: b256!("a312b4510adf943510f05fcc8f15f86995a5066bd83ce11384688ae20e6ecf42"), + from: address!("4210000000000000000000000000000000000001"), to: None, mint: None, - value: U256::from(0), - gas: U256::from(1_000_000), + value: U256::ZERO(), + gas: uint!(1_000_000_U256), is_system_tx: false, input: Bytes::from_str("0x608060405234801561001057600080fd5b50610fb5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806354fd4d5011610097578063de26c4a111610066578063de26c4a1146101da578063f45e65d8146101ed578063f8206140146101f5578063fe173b97146101cc57600080fd5b806354fd4d501461016657806368d5dca6146101af5780636ef25c3a146101cc578063c5985918146101d257600080fd5b8063313ce567116100d3578063313ce5671461012757806349948e0e1461012e5780634ef6e22414610141578063519b4bd31461015e57600080fd5b80630c18c162146100fa57806322b90ab3146101155780632e0f26251461011f575b600080fd5b6101026101fd565b6040519081526020015b60405180910390f35b61011d61031e565b005b610102600681565b6006610102565b61010261013c366004610b73565b610541565b60005461014e9060ff1681565b604051901515815260200161010c565b610102610565565b6101a26040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161010c9190610c42565b6101b76105c6565b60405163ffffffff909116815260200161010c565b48610102565b6101b761064b565b6101026101e8366004610b73565b6106ac565b610102610760565b610102610853565b6000805460ff1615610296576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f47617350726963654f7261636c653a206f76657268656164282920697320646560448201527f707265636174656400000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610cb5565b905090565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663e591b2826040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a19190610cce565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e2073657420697345636f746f6e6520666c6160648201527f6700000000000000000000000000000000000000000000000000000000000000608482015260a40161028d565b60005460ff1615610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a2045636f746f6e6520616c72656164792060448201527f6163746976650000000000000000000000000000000000000000000000000000606482015260840161028d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000805460ff161561055c57610556826108b4565b92915050565b61055682610958565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff166368d5dca66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610d04565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663c59859186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b6000806106b883610ab4565b60005490915060ff16156106cc5792915050565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561072b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074f9190610cb5565b6107599082610d59565b9392505050565b6000805460ff16156107f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a207363616c61722829206973206465707260448201527f6563617465640000000000000000000000000000000000000000000000000000606482015260840161028d565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663f82061406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b6000806108c083610ab4565b905060006108cc610565565b6108d461064b565b6108df906010610d71565b63ffffffff166108ef9190610d9d565b905060006108fb610853565b6109036105c6565b63ffffffff166109139190610d9d565b905060006109218284610d59565b61092b9085610d9d565b90506109396006600a610efa565b610944906010610d9d565b61094e9082610f06565b9695505050505050565b60008061096483610ab4565b9050600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109eb9190610cb5565b6109f3610565565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a769190610cb5565b610a809085610d59565b610a8a9190610d9d565b610a949190610d9d565b9050610aa26006600a610efa565b610aac9082610f06565b949350505050565b80516000908190815b81811015610b3757848181518110610ad757610ad7610f41565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016600003610b1757610b10600484610d59565b9250610b25565b610b22601084610d59565b92505b80610b2f81610f70565b915050610abd565b50610aac82610440610d59565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610b8557600080fd5b813567ffffffffffffffff80821115610b9d57600080fd5b818401915084601f830112610bb157600080fd5b813581811115610bc357610bc3610b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610c0957610c09610b44565b81604052828152876020848701011115610c2257600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b81811015610c6f57858101830151858201604001528201610c53565b81811115610c81576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610cc757600080fd5b5051919050565b600060208284031215610ce057600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461075957600080fd5b600060208284031215610d1657600080fd5b815163ffffffff8116811461075957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610d6c57610d6c610d2a565b500190565b600063ffffffff80831681851681830481118215151615610d9457610d94610d2a565b02949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610dd557610dd5610d2a565b500290565b600181815b80851115610e3357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610e1957610e19610d2a565b80851615610e2657918102915b93841c9390800290610ddf565b509250929050565b600082610e4a57506001610556565b81610e5757506000610556565b8160018114610e6d5760028114610e7757610e93565b6001915050610556565b60ff841115610e8857610e88610d2a565b50506001821b610556565b5060208310610133831016604e8410600b8410161715610eb6575081810a610556565b610ec08383610dda565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610ef257610ef2610d2a565b029392505050565b60006107598383610e3b565b600082610f3c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610fa157610fa1610d2a565b506001019056fea164736f6c634300080f000a").unwrap(), ..Default::default() @@ -47,15 +59,13 @@ pub fn get_ecotone_upgrade_transactions() -> Vec { let update_l1_block_proxy = Transaction { transaction_type: Some(U64::from(0x7E)), - source_hash: H256::from_str( - "0x18acb38c5ff1c238a7460ebc1b421fa49ec4874bdf1e0a530d234104e5e67dbc", - ) + source_hash: b256!("18acb38c5ff1c238a7460ebc1b421fa49ec4874bdf1e0a530d234104e5e67dbc") .unwrap(), - from: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), - to: Some(Address::from_str("0x4200000000000000000000000000000000000015").unwrap()), + from: address!("0000000000000000000000000000000000000000"), + to: Some(address!("4200000000000000000000000000000000000015")), mint: None, - value: U256::from(0), - gas: U256::from(50_000), + value: U256::ZERO(), + gas: uint!(50_000_U256), is_system_tx: false, input: Bytes::from_str( "0x3659cfe600000000000000000000000007dbe8500fc591d1852b76fee44d5a05e13097ff", @@ -67,15 +77,12 @@ pub fn get_ecotone_upgrade_transactions() -> Vec { let update_gas_price_oracle_proxy = Transaction { transaction_type: Some(U64::from(0x7E)), - source_hash: H256::from_str( - "0xee4f9385eceef498af0be7ec5862229f426dec41c8d42397c7257a5117d9230a", - ) - .unwrap(), - from: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), + source_hash: b256!("ee4f9385eceef498af0be7ec5862229f426dec41c8d42397c7257a5117d9230a"), + from: address!("0000000000000000000000000000000000000000"), to: Some(Address::from_str("0x420000000000000000000000000000000000000F").unwrap()), mint: None, - value: U256::from(0), - gas: U256::from(50_000), + value: U256::ZERO(), + gas: uint!(50_000_U256), is_system_tx: false, input: Bytes::from_str( "0x3659cfe6000000000000000000000000b528d11cc114e026f138fe568744c6d45ce6da7a", @@ -87,15 +94,12 @@ pub fn get_ecotone_upgrade_transactions() -> Vec { let enable_ecotone = Transaction { transaction_type: Some(U64::from(0x7E)), - source_hash: H256::from_str( - "0x0c1cb38e99dbc9cbfab3bb80863380b0905290b37eb3d6ab18dc01c1f3e75f93", - ) - .unwrap(), - from: Address::from_str("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001").unwrap(), - to: Some(Address::from_str("0x420000000000000000000000000000000000000F").unwrap()), + source_hash: b256!("0c1cb38e99dbc9cbfab3bb80863380b0905290b37eb3d6ab18dc01c1f3e75f93"), + from: address!("DeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001"), + to: Some(address!("420000000000000000000000000000000000000F")), mint: None, - value: U256::from(0), - gas: U256::from(80_000), + value: U256::ZERO(), + gas: uint!(80_000_U256), is_system_tx: false, input: Bytes::from_str("0x22b90ab3").unwrap(), ..Default::default() @@ -104,15 +108,12 @@ pub fn get_ecotone_upgrade_transactions() -> Vec { let deploy_eip4788 = Transaction { transaction_type: Some(U64::from(0x7E)), - source_hash: H256::from_str( - "0x69b763c48478b9dc2f65ada09b3d92133ec592ea715ec65ad6e7f3dc519dc00c", - ) - .unwrap(), - from: Address::from_str("0x0B799C86a49DEeb90402691F1041aa3AF2d3C875").unwrap(), + source_hash: b256!("69b763c48478b9dc2f65ada09b3d92133ec592ea715ec65ad6e7f3dc519dc00c"), + from: address!("0B799C86a49DEeb90402691F1041aa3AF2d3C875"), to: None, mint: None, - value: U256::from(0), - gas: U256::from(0x3d090), + value: U256::ZERO(), + gas: uint!(0x3d090_U256), is_system_tx: false, input: Bytes::from_str("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500").unwrap(), ..Default::default() diff --git a/src/derive/mod.rs b/src/derive/mod.rs index 6ebf391..e880990 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -1,204 +1,15 @@ -use std::sync::{mpsc, Arc, RwLock}; +//! The `derive` module contains the stages and orchestration for the derivation pipeline. -use bytes::Bytes; -use eyre::Result; - -use crate::{config::Config, engine::PayloadAttributes}; - -use self::{ - stages::{ - attributes::Attributes, - batcher_transactions::{BatcherTransactionMessage, BatcherTransactions}, - batches::Batches, - channels::Channels, - }, - state::State, -}; - -/// A module that handles the block derivation stages pub mod stages; -/// A module that keeps track of the current derivation state, caching previous L1 and L2 blocks + pub mod state; +pub use state::State; -/// A module that handles the Ecotone hardfork upgrade pub mod ecotone_upgrade; pub use ecotone_upgrade::get_ecotone_upgrade_transactions; -/// A module that extends the [Iterator] trait with a `purge` method -mod purgeable; +pub mod purgeable; pub use purgeable::PurgeableIterator; -/// The derivation pipeline is iterated on to update attributes for new blocks. -pub struct Pipeline { - /// A channel sender to send a `BatcherTransactionMessage` - batcher_transaction_sender: mpsc::Sender, - /// An `Attributes` object - attributes: Attributes, - /// Pending `PayloadAttributes` - pending_attributes: Option, -} - -impl Iterator for Pipeline { - type Item = PayloadAttributes; - - /// Returns the pending [PayloadAttributes]. - /// If none exist it will call `Attributes::next()` to advance to the next block and return those attributes instead. - fn next(&mut self) -> Option { - if self.pending_attributes.is_some() { - self.pending_attributes.take() - } else { - self.attributes.next() - } - } -} - -impl Pipeline { - /// Creates a new [Pipeline] and initializes [BatcherTransactions], [Channels], [Batches], and [Attributes] - pub fn new(state: Arc>, config: Arc, seq: u64) -> Result { - let (tx, rx) = mpsc::channel(); - let batcher_transactions = BatcherTransactions::new(rx); - let channels = Channels::new(batcher_transactions, config.clone()); - let batches = Batches::new(channels, state.clone(), config.clone()); - let attributes = Attributes::new(Box::new(batches), state, config, seq); - - Ok(Self { - batcher_transaction_sender: tx, - attributes, - pending_attributes: None, - }) - } - - /// Sends [BatcherTransactions] & the L1 block they were received in to the [BatcherTransactions] receiver. - pub fn push_batcher_transactions( - &self, - txs: Vec, - l1_origin: u64, - ) -> Result<()> { - let txs = txs.into_iter().map(Bytes::from).collect(); - self.batcher_transaction_sender - .send(BatcherTransactionMessage { txs, l1_origin })?; - Ok(()) - } - - /// Returns a reference to the pending [PayloadAttributes]. - /// If none are pending, it will call `self.next()` to advance to the next block and return those attributes instead. - pub fn peek(&mut self) -> Option<&PayloadAttributes> { - if self.pending_attributes.is_none() { - let next_attributes = self.next(); - self.pending_attributes = next_attributes; - } - - self.pending_attributes.as_ref() - } - - /// Resets the state of `self.attributes` by calling `Attributes::purge()` - pub fn purge(&mut self) -> Result<()> { - self.attributes.purge(); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use std::{ - env, - sync::{Arc, RwLock}, - }; - - use ethers::{ - providers::{Middleware, Provider}, - types::H256, - utils::keccak256, - }; - - use crate::{ - common::RawTransaction, - config::{ChainConfig, Config}, - derive::*, - l1::{BlockUpdate, ChainWatcher}, - }; - - #[tokio::test(flavor = "multi_thread")] - async fn test_attributes_match() { - if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() { - let rpc = env::var("L1_TEST_RPC_URL").unwrap(); - let l2_rpc = env::var("L2_TEST_RPC_URL").unwrap(); - - let config = Arc::new(Config { - l1_rpc_url: rpc.to_string(), - l1_beacon_url: String::new(), - l2_rpc_url: l2_rpc.to_string(), - chain: ChainConfig::optimism_goerli(), - l2_engine_url: String::new(), - jwt_secret: String::new(), - checkpoint_sync_url: None, - rpc_port: 9545, - rpc_addr: "127.0.0.1".to_string(), - devnet: false, - }); - - let mut chain_watcher = ChainWatcher::new( - config.chain.l1_start_epoch.number, - config.chain.l2_genesis.number, - config.clone(), - ) - .unwrap(); - - chain_watcher.start().unwrap(); - - let provider = Provider::try_from(env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); - let state = Arc::new(RwLock::new( - State::new( - config.chain.l2_genesis, - config.chain.l1_start_epoch, - &provider, - config.clone(), - ) - .await, - )); - - let mut pipeline = Pipeline::new(state.clone(), config.clone(), 0).unwrap(); - - chain_watcher.recv_from_channel().await.unwrap(); - let update = chain_watcher.recv_from_channel().await.unwrap(); - - let l1_info = match update { - BlockUpdate::NewBlock(block) => *block, - _ => panic!("wrong update type"), - }; - - pipeline - .push_batcher_transactions( - l1_info.batcher_transactions.clone(), - l1_info.block_info.number, - ) - .unwrap(); - - state.write().unwrap().update_l1_info(l1_info); - - if let Some(payload) = pipeline.next() { - let hashes = get_tx_hashes(&payload.transactions.unwrap()); - let expected_hashes = get_expected_hashes(config.chain.l2_genesis.number + 1).await; - - assert_eq!(hashes, expected_hashes); - } - } - } - - async fn get_expected_hashes(block_num: u64) -> Vec { - let provider = Provider::try_from(env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); - - provider - .get_block(block_num) - .await - .unwrap() - .unwrap() - .transactions - } - - fn get_tx_hashes(txs: &[RawTransaction]) -> Vec { - txs.iter() - .map(|tx| H256::from_slice(&keccak256(&tx.0))) - .collect() - } -} +pub mod pipeline; +pub use pipeline::Pipeline; diff --git a/src/derive/pipeline.rs b/src/derive/pipeline.rs new file mode 100644 index 0000000..cc45c8b --- /dev/null +++ b/src/derive/pipeline.rs @@ -0,0 +1,193 @@ +//! Contains the pipeline implementation. + +use std::sync::{mpsc, Arc, RwLock}; +use alloy_primitives::Bytes; +use eyre::Result; + +use crate::{config::Config, engine::PayloadAttributes}; + +use crate::derive::{ + stages::{ + attributes::Attributes, + batcher_transactions::{BatcherTransactionMessage, BatcherTransactions}, + batches::Batches, + channels::Channels, + }, + state::State, + purgeable::PurgeableIterator, +}; + +/// The derivation pipeline is iterated on to update attributes for new blocks. +pub struct Pipeline { + /// A channel sender to send a `BatcherTransactionMessage` + batcher_transaction_sender: mpsc::Sender, + /// An `Attributes` object + attributes: Attributes, + /// Pending `PayloadAttributes` + pending_attributes: Option, +} + +impl Iterator for Pipeline { + type Item = PayloadAttributes; + + /// Returns the pending [PayloadAttributes]. + /// If none exist it will call `Attributes::next()` to advance to the next block and return those attributes instead. + fn next(&mut self) -> Option { + if self.pending_attributes.is_some() { + self.pending_attributes.take() + } else { + self.attributes.next() + } + } +} + +impl Pipeline { + /// Creates a new [Pipeline] and initializes [BatcherTransactions], [Channels], [Batches], and [Attributes] + pub fn new(state: Arc>, config: Arc, seq: u64) -> Result { + let (tx, rx) = mpsc::channel(); + let batcher_transactions = BatcherTransactions::new(rx); + let channels = Channels::new(batcher_transactions, config.clone()); + let batches = Batches::new(channels, state.clone(), config.clone()); + let attributes = Attributes::new(Box::new(batches), state, config, seq); + + Ok(Self { + batcher_transaction_sender: tx, + attributes, + pending_attributes: None, + }) + } + + /// Sends [BatcherTransactions] & the L1 block they were received in to the [BatcherTransactions] receiver. + pub fn push_batcher_transactions( + &self, + txs: Vec, + l1_origin: u64, + ) -> Result<()> { + let txs = txs.into_iter().map(Bytes::from).collect(); + self.batcher_transaction_sender + .send(BatcherTransactionMessage { txs, l1_origin })?; + Ok(()) + } + + /// Returns a reference to the pending [PayloadAttributes]. + /// If none are pending, it will call `self.next()` to advance to the next block and return those attributes instead. + pub fn peek(&mut self) -> Option<&PayloadAttributes> { + if self.pending_attributes.is_none() { + let next_attributes = self.next(); + self.pending_attributes = next_attributes; + } + + self.pending_attributes.as_ref() + } + + /// Resets the state of `self.attributes` by calling `Attributes::purge()` + pub fn purge(&mut self) -> Result<()> { + self.attributes.purge(); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::{ + env, + sync::{Arc, RwLock}, + }; + + use ethers::{ + providers::{Middleware, Provider}, + types::H256, + utils::keccak256, + }; + + use crate::{ + common::RawTransaction, + config::{ChainConfig, Config}, + derive::*, + l1::{BlockUpdate, ChainWatcher}, + }; + + #[tokio::test(flavor = "multi_thread")] + async fn test_attributes_match() { + if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() { + let rpc = env::var("L1_TEST_RPC_URL").unwrap(); + let l2_rpc = env::var("L2_TEST_RPC_URL").unwrap(); + + let config = Arc::new(Config { + l1_rpc_url: rpc.to_string(), + l1_beacon_url: String::new(), + l2_rpc_url: l2_rpc.to_string(), + chain: ChainConfig::optimism_goerli(), + l2_engine_url: String::new(), + jwt_secret: String::new(), + checkpoint_sync_url: None, + rpc_port: 9545, + rpc_addr: "127.0.0.1".to_string(), + devnet: false, + }); + + let mut chain_watcher = ChainWatcher::new( + config.chain.l1_start_epoch.number, + config.chain.l2_genesis.number, + config.clone(), + ) + .unwrap(); + + chain_watcher.start().unwrap(); + + let provider = Provider::try_from(env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); + let state = Arc::new(RwLock::new( + State::new( + config.chain.l2_genesis, + config.chain.l1_start_epoch, + &provider, + config.clone(), + ) + .await, + )); + + let mut pipeline = Pipeline::new(state.clone(), config.clone(), 0).unwrap(); + + chain_watcher.recv_from_channel().await.unwrap(); + let update = chain_watcher.recv_from_channel().await.unwrap(); + + let l1_info = match update { + BlockUpdate::NewBlock(block) => *block, + _ => panic!("wrong update type"), + }; + + pipeline + .push_batcher_transactions( + l1_info.batcher_transactions.clone(), + l1_info.block_info.number, + ) + .unwrap(); + + state.write().unwrap().update_l1_info(l1_info); + + if let Some(payload) = pipeline.next() { + let hashes = get_tx_hashes(&payload.transactions.unwrap()); + let expected_hashes = get_expected_hashes(config.chain.l2_genesis.number + 1).await; + + assert_eq!(hashes, expected_hashes); + } + } + } + + async fn get_expected_hashes(block_num: u64) -> Vec { + let provider = Provider::try_from(env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); + + provider + .get_block(block_num) + .await + .unwrap() + .unwrap() + .transactions + } + + fn get_tx_hashes(txs: &[RawTransaction]) -> Vec { + txs.iter() + .map(|tx| H256::from_slice(&keccak256(&tx.0))) + .collect() + } +} diff --git a/src/derive/purgeable.rs b/src/derive/purgeable.rs index 27c2d10..cf3486a 100644 --- a/src/derive/purgeable.rs +++ b/src/derive/purgeable.rs @@ -1,3 +1,5 @@ +//! Defines an [Iterator] that can purge itself. + /// Iterator that can purge itself pub trait PurgeableIterator: Iterator { /// Purges and resets an iterator diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 3729ffb..6a46dcb 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -1,12 +1,14 @@ +//! A module to handle the payload attributes derivation stage. + use std::sync::{Arc, RwLock}; +use alloy_rlp::Encodable; +use alloy_primitives::{Address, B256, keccak256, U64, U256}; + use ethers::abi::{decode, encode, ParamType, Token}; -use ethers::types::{Address, H256, U256}; -use ethers::utils::{keccak256, rlp::Encodable, rlp::RlpStream}; use eyre::Result; -use alloy_primitives::U64; use crate::common::{Epoch, RawTransaction}; use crate::config::{Config, SystemAccounts}; use crate::derive::state::State; @@ -25,7 +27,7 @@ pub struct Attributes { /// The sequence number of the block being processed sequence_number: u64, /// The block hash of the corresponding L1 epoch block. - epoch_hash: H256, + epoch_hash: B256, /// The global Magi [Config] config: Arc, } @@ -48,7 +50,7 @@ impl PurgeableIterator for Attributes { self.block_input_iter.purge(); self.sequence_number = 0; self.epoch_hash = - ethers::types::H256::from_slice(self.state.read().unwrap().safe_epoch.hash.as_slice()); + self.state.read().unwrap().safe_epoch.hash; } } @@ -66,7 +68,7 @@ impl Attributes { block_input_iter, state, sequence_number: seq, - epoch_hash: H256::from_slice(epoch_hash.as_slice()), + epoch_hash, config, } } @@ -78,11 +80,10 @@ impl Attributes { tracing::debug!("deriving attributes from block: {}", input.epoch.number); tracing::debug!("batch epoch hash: {:?}", input.epoch.hash); - let epoch_hash = H256::from_slice(input.epoch.hash.as_slice()); - self.update_sequence_number(epoch_hash); + self.update_sequence_number(input.epoch.hash); let state = self.state.read().unwrap(); - let l1_info = state.l1_info_by_hash(epoch_hash).unwrap(); + let l1_info = state.l1_info_by_hash(input.epoch.hash).unwrap(); let withdrawals = if input.timestamp >= self.config.chain.canyon_time { Some(Vec::new()) @@ -98,12 +99,12 @@ impl Attributes { let suggested_fee_recipient = SystemAccounts::default().fee_vault; PayloadAttributes { - timestamp: alloy_primitives::U64::from(input.timestamp), + timestamp: U64::from(input.timestamp), prev_randao, suggested_fee_recipient, transactions, no_tx_pool: true, - gas_limit: alloy_primitives::U64::from(l1_info.system_config.gas_limit), + gas_limit: U64::from(l1_info.system_config.gas_limit), withdrawals, epoch, l1_inclusion_block, @@ -185,7 +186,7 @@ impl Attributes { /// Sets the current sequence number. If `self.epoch_hash` != `batch_epoch_hash` this is set to 0; otherwise it increments by 1. /// /// Also sets `self.epoch_hash` to `batch_epoch_hash` - fn update_sequence_number(&mut self, batch_epoch_hash: H256) { + fn update_sequence_number(&mut self, batch_epoch_hash: B256) { if self.epoch_hash != batch_epoch_hash { self.sequence_number = 0; } else { @@ -197,10 +198,10 @@ impl Attributes { } /// Represents a deposited transaction -#[derive(Debug)] -struct DepositedTransaction { +#[derive(Debug, Clone)] +pub struct DepositedTransaction { /// Unique identifier to identify the origin of the deposit - source_hash: H256, + source_hash: B256, /// Address of the sender from: Address, /// Address of the recipient, or None if the transaction is a contract creation @@ -220,12 +221,12 @@ struct DepositedTransaction { impl From for DepositedTransaction { /// Converts [AttributesDeposited] to a [DepositedTransaction] fn from(attributes_deposited: AttributesDeposited) -> Self { - let hash = attributes_deposited.hash.to_fixed_bytes(); - let seq = H256::from_low_u64_be(attributes_deposited.sequence_number).to_fixed_bytes(); + let hash = attributes_deposited.hash; + let seq = B256::from_slice(&attributes_deposited.sequence_number.to_be_bytes()); let h = keccak256([hash, seq].concat()); - let domain = H256::from_low_u64_be(1).to_fixed_bytes(); - let source_hash = H256::from_slice(&keccak256([domain, h].concat())); + let domain = B256::from_slice(&1u64.to_be_bytes()); + let source_hash = keccak256([domain, h].concat()); let system_accounts = SystemAccounts::default(); let from = system_accounts.attributes_depositor; @@ -235,10 +236,10 @@ impl From for DepositedTransaction { Self { source_hash, - from: Address::from_slice(from.as_slice()), - to: to.map(|t| Address::from_slice(t.as_slice())), - mint: U256::zero(), - value: U256::zero(), + from, + to, + mint: U256::ZERO, + value: U256::ZERO, gas: attributes_deposited.gas, is_system_tx: attributes_deposited.is_system_tx, data, @@ -249,12 +250,12 @@ impl From for DepositedTransaction { impl From for DepositedTransaction { /// Converts [UserDeposited] to a [DepositedTransaction] fn from(user_deposited: UserDeposited) -> Self { - let hash = user_deposited.l1_block_hash.to_fixed_bytes(); + let hash = user_deposited.l1_block_hash; let log_index = user_deposited.log_index.into(); let h = keccak256([hash, log_index].concat()); - let domain = H256::from_low_u64_be(0).to_fixed_bytes(); - let source_hash = H256::from_slice(&keccak256([domain, h].concat())); + let domain = B256::ZERO; + let source_hash = keccak256([domain, h].concat()); let to = if user_deposited.is_creation { None @@ -276,6 +277,16 @@ impl From for DepositedTransaction { } impl Encodable for DepositedTransaction { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + out.put(&[0x7E]); + out.put_u8(8); // Start the list + + out.put(&self.source_hash); + + } +} + +impl Encodable for { /// Converts a [DepositedTransaction] to RLP bytes and appends to the stream. fn rlp_append(&self, s: &mut RlpStream) { s.append_raw(&[0x7E], 1); @@ -299,7 +310,7 @@ impl Encodable for DepositedTransaction { /// Represents the attributes provided as calldata in an attributes deposited transaction. #[derive(Debug)] -struct AttributesDeposited { +pub struct AttributesDeposited { /// The L1 epoch block number number: u64, /// The L1 epoch block timestamp @@ -307,11 +318,11 @@ struct AttributesDeposited { /// The L1 epoch base fee base_fee: U256, /// The L1 epoch block hash - hash: H256, + hash: B256, /// The L2 block's position in the epoch sequence_number: u64, /// A versioned hash of the current authorized batcher sender. - batcher_hash: H256, + batcher_hash: B256, /// The current L1 fee overhead to apply to L2 transactions cost computation. Unused after Ecotone hard fork. fee_overhead: U256, /// The current L1 fee scalar to apply to L2 transactions cost computation. Unused after Ecotone hard fork. @@ -330,14 +341,14 @@ impl AttributesDeposited { let gas = if is_regolith { 1_000_000 } else { 150_000_000 }; - let batcher_hash = H256::from_slice(l1_info.system_config.batcher_hash().as_slice()); - let fee_overhead = U256::from(l1_info.system_config.l1_fee_overhead.to_be_bytes()); - let fee_scalar = U256::from(l1_info.system_config.l1_fee_scalar.to_be_bytes()); + let batcher_hash = l1_info.system_config.batcher_hash(); + let fee_overhead = l1_info.system_config.l1_fee_overhead; + let fee_scalar = l1_info.system_config.l1_fee_scalar; Self { number: l1_info.block_info.number, timestamp: l1_info.block_info.timestamp, - base_fee: U256::from_big_endian(&l1_info.block_info.base_fee.to_be_bytes::<32>()), - hash: H256::from_slice(l1_info.block_info.hash.as_slice()), + base_fee: l1_info.block_info.base_fee, + hash: l1_info.block_info.hash, sequence_number: seq, batcher_hash, fee_overhead, @@ -353,9 +364,9 @@ impl AttributesDeposited { Token::Uint(self.number.into()), Token::Uint(self.timestamp.into()), Token::Uint(self.base_fee), - Token::FixedBytes(self.hash.as_fixed_bytes().to_vec()), + Token::FixedBytes(self.hash.to_vec()), Token::Uint(self.sequence_number.into()), - Token::FixedBytes(self.batcher_hash.as_fixed_bytes().to_vec()), + Token::FixedBytes(self.batcher_hash.to_vec()), Token::Uint(self.fee_overhead), Token::Uint(self.fee_scalar), ]; @@ -387,7 +398,7 @@ pub struct UserDeposited { /// The L1 block number this was submitted in. pub l1_block_num: u64, /// The L1 block hash this was submitted in. - pub l1_block_hash: H256, + pub l1_block_hash: B256, /// The index of the emitted deposit event log in the L1 block. pub log_index: U256, } @@ -411,8 +422,8 @@ impl TryFrom for UserDeposited { let from = Address::from_slice(log.topics()[1].as_slice()); let to = Address::from_slice(log.topics()[2].as_slice()); - let mint = U256::from_big_endian(&opaque_data[0..32]); - let value = U256::from_big_endian(&opaque_data[32..64]); + let mint = U256::from_be_slice(&opaque_data[0..32]); + let value = U256::from_be_slice(&opaque_data[32..64]); let gas = u64::from_be_bytes(opaque_data[64..72].try_into()?); let is_creation = opaque_data[72] != 0; let data = opaque_data[73..].to_vec(); @@ -420,7 +431,7 @@ impl TryFrom for UserDeposited { let l1_block_num = log.block_number.ok_or(eyre::eyre!("block num not found"))?; let l1_block_hash = log.block_hash.ok_or(eyre::eyre!("block hash not found"))?; - let log_index = log.log_index.unwrap(); + let log_index = U256::from(log.log_index.unwrap()); Ok(Self { from, @@ -431,8 +442,8 @@ impl TryFrom for UserDeposited { is_creation, data, l1_block_num, - l1_block_hash: H256::from_slice(l1_block_hash.as_slice()), - log_index: log_index.into(), + l1_block_hash, + log_index, }) } } diff --git a/src/derive/stages/batcher_transactions.rs b/src/derive/stages/batcher_transactions.rs index d29be46..0e6e85b 100644 --- a/src/derive/stages/batcher_transactions.rs +++ b/src/derive/stages/batcher_transactions.rs @@ -1,14 +1,17 @@ +//! A module to handle batcher transactions and frames + use std::sync::mpsc; use eyre::Result; use std::collections::VecDeque; +use alloy_primitives::Bytes; use crate::derive::PurgeableIterator; /// Represents a transaction sent to the `Batch Inbox` on L1. pub struct BatcherTransactionMessage { /// The L2 transactions included in this batch - pub txs: Vec, + pub txs: Vec, /// The L1 block number this transaction was included in pub l1_origin: u64, } @@ -178,7 +181,7 @@ mod tests { #[test] fn test_push_tx() { - let data = bytes::Bytes::from(hex::decode(TX_DATA).unwrap()); + let data = Bytes::from(hex::decode(TX_DATA).unwrap()); let txs = vec![data]; let (tx, rx) = mpsc::channel(); diff --git a/src/derive/stages/batches.rs b/src/derive/stages/batches.rs index 35c674a..84e0575 100644 --- a/src/derive/stages/batches.rs +++ b/src/derive/stages/batches.rs @@ -1,11 +1,13 @@ +//! A module to handle processing of a [Batch]. + +use alloy_rlp::Rlp; +use alloy_rlp::Decodable; use core::fmt::Debug; use std::cmp::Ordering; use std::collections::BTreeMap; use std::io::Read; use std::sync::{Arc, RwLock}; -use alloy_rlp::Decodable; -use ethers::utils::rlp::Rlp; use eyre::Result; use libflate::zlib::Decoder; @@ -215,7 +217,9 @@ where tracing::warn!("missing inclusion block"); return BatchStatus::Drop; } - if batch.epoch_num + self.config.chain.seq_window_size < batch.l1_inclusion_block.unwrap_or(0) { + if batch.epoch_num + self.config.chain.seq_window_size + < batch.l1_inclusion_block.unwrap_or(0) + { tracing::warn!("inclusion window elapsed"); return BatchStatus::Drop; } @@ -231,8 +235,7 @@ where }; if let Some(batch_origin) = batch_origin { - if batch.epoch_hash != batch_origin.hash - { + if batch.epoch_hash != batch_origin.hash { tracing::warn!("invalid epoch hash"); return BatchStatus::Drop; } @@ -426,10 +429,7 @@ fn decode_batches(channel: &Channel, chain_id: u64) -> Result> { let mut offset = 0; while offset < channel_data.len() { - let batch_rlp = Rlp::new(&channel_data[offset..]); - let batch_info = batch_rlp.payload_info()?; - - let batch_data: Vec = batch_rlp.as_val()?; + let batch_data = &channel_data[offset..]; let version = batch_data[0]; let batch_content = &batch_data[1..]; @@ -437,13 +437,13 @@ fn decode_batches(channel: &Channel, chain_id: u64) -> Result> { match version { 0 => { let rlp = Rlp::new(batch_content); - let size = rlp.payload_info()?.total(); + let size = rlp.get_next::()?.ok_or_else(|| eyre::eyre!("failed to get header"))?.len(); let mut batch = SingleBatch::decode(&mut batch_content)?; batch.l1_inclusion_block = Some(channel.l1_inclusion_block); batches.push(Batch::Single(batch)); - offset += size + batch_info.header_len + 1; + offset += size + 1; } 1 => { let batch = SpanBatch::decode(batch_content, channel.l1_inclusion_block, chain_id)?; diff --git a/src/derive/stages/mod.rs b/src/derive/stages/mod.rs index b8586b7..379317f 100644 --- a/src/derive/stages/mod.rs +++ b/src/derive/stages/mod.rs @@ -1,11 +1,13 @@ -/// A module to handle the payload attributes derivation stage +//! A module defining the stages of the derivation pipeline. + pub mod attributes; +pub use attributes::{Attributes, DepositedTransaction, AttributesDeposited, UserDeposited}; -/// A module to handle batcher transactions and frames pub mod batcher_transactions; +pub use batcher_transactions::{BatcherTransactions, BatcherTransactionMessage, BatcherTransaction, Frame}; -/// A module to handle processing of a [Batch](crate::derive::stages::batches::Batch) pub mod batches; +pub use batches::Batches; /// A module to handle building a [BlockInput](crate::derive::stages::block_input::BlockInput) mod block_input; diff --git a/src/derive/state.rs b/src/derive/state.rs index 3cf3ab9..7d6b6e0 100644 --- a/src/derive/state.rs +++ b/src/derive/state.rs @@ -1,9 +1,10 @@ +//! A module that keeps track of the current derivation state. +//! The [State] caches previous L1 and L2 blocks. + use std::{collections::BTreeMap, sync::Arc}; -use ethers::{ - providers::{Http, Middleware, Provider}, - types::H256, -}; +use alloy_primitives::B256; +use alloy_provider::Provider; use crate::{ common::{BlockInfo, Epoch}, @@ -12,12 +13,13 @@ use crate::{ l1::L1Info, }; -/// Represents the current derivation state. Consists of cached L1 & L2 blocks, and details of the current safe head & safe epoch. +/// Represents the current derivation state. +/// Consists of cached L1 & L2 blocks, and details of the current safe head & safe epoch. pub struct State { /// Map of L1 blocks from the current L1 safe epoch - ``seq_window_size`` - l1_info: BTreeMap, + l1_info: BTreeMap, /// Map of L1 block hashes from the current L1 safe epoch - ``seq_window_size`` - l1_hashes: BTreeMap, + l1_hashes: BTreeMap, /// Map of L2 blocks from the current L2 safe head - (``max_seq_drift`` / ``blocktime``) l2_refs: BTreeMap, /// The current safe head @@ -35,7 +37,7 @@ impl State { pub async fn new( finalized_head: BlockInfo, finalized_epoch: Epoch, - provider: &Provider, + provider: &dyn Provider, config: Arc, ) -> Self { let l2_refs = l2_refs(finalized_head.number, provider, &config).await; @@ -52,7 +54,7 @@ impl State { } /// Returns a cached L1 block by block hash - pub fn l1_info_by_hash(&self, hash: H256) -> Option<&L1Info> { + pub fn l1_info_by_hash(&self, hash: B256) -> Option<&L1Info> { self.l1_info.get(&hash) } @@ -73,7 +75,7 @@ impl State { } /// Returns an epoch from an L1 block hash - pub fn epoch_by_hash(&self, hash: H256) -> Option { + pub fn epoch_by_hash(&self, hash: B256) -> Option { self.l1_info_by_hash(hash).map(|info| Epoch { number: info.block_info.number, hash: info.block_info.hash, @@ -95,16 +97,11 @@ impl State { /// This also updates ``current_epoch_num`` to the block number of the given ``l1_info``. pub fn update_l1_info(&mut self, l1_info: L1Info) { self.current_epoch_num = l1_info.block_info.number; - self.l1_hashes.insert( l1_info.block_info.number, - H256::from_slice(l1_info.block_info.hash.as_slice()), + l1_info.block_info.hash, ); - self.l1_info.insert( - H256::from_slice(l1_info.block_info.hash.as_slice()), - l1_info, - ); - + self.l1_info.insert(l1_info.block_info.hash, l1_info); self.prune(); } @@ -168,7 +165,7 @@ impl State { /// If the lookback period is before the genesis block, it will return L2 blocks starting from genesis. async fn l2_refs( head_num: u64, - provider: &Provider, + provider: &dyn Provider, config: &Config, ) -> BTreeMap { let lookback = config.chain.max_seq_drift / config.chain.blocktime; @@ -178,7 +175,7 @@ async fn l2_refs( let mut refs = BTreeMap::new(); for i in start..=head_num { - let l2_block = provider.get_block_with_txs(i).await; + let l2_block = provider.get_block(i.into(), true).await; if let Ok(Some(l2_block)) = l2_block { match HeadInfo::try_from_l2_block(config, l2_block) { Ok(head_info) => { diff --git a/src/driver/engine_driver.rs b/src/driver/engine_driver.rs index 8881a7f..38ddacc 100644 --- a/src/driver/engine_driver.rs +++ b/src/driver/engine_driver.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use alloy_primitives::keccak256; -use alloy_rpc_types::{BlockTransactions, Block}; use alloy_provider::{Provider, ReqwestProvider}; +use alloy_rpc_types::{Block, BlockTransactions}; use eyre::Result; use crate::{ @@ -113,11 +113,7 @@ impl EngineDriver { } /// Updates the forkchoice by sending `engine_forkchoiceUpdatedV2` (v3 post Ecotone) to the engine with no payload. - async fn skip_attributes( - &mut self, - attributes: PayloadAttributes, - block: Block, - ) -> Result<()> { + async fn skip_attributes(&mut self, attributes: PayloadAttributes, block: Block) -> Result<()> { let new_epoch = *attributes.epoch.as_ref().unwrap(); let new_head = BlockInfo::try_from(block)?; self.update_safe_head(new_head, new_epoch, false)?; @@ -236,19 +232,18 @@ fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Result { return Ok(true); }; - let block_hashes = txs - .iter() - .map(|tx| tx.hash()) - .collect::>(); + let block_hashes = txs.iter().map(|tx| tx.hash()).collect::>(); tracing::debug!("attribute hashes: {:?}", attributes_hashes); tracing::debug!("block hashes: {:?}", block_hashes); let is_same = attributes_hashes == block_hashes && attributes.timestamp == block.header.timestamp - && block.header.mix_hash.map_or(false, |m| m == attributes.prev_randao) - && attributes.suggested_fee_recipient - == block.header.miner + && block + .header + .mix_hash + .map_or(false, |m| m == attributes.prev_randao) + && attributes.suggested_fee_recipient == block.header.miner && attributes.gas_limit == block.header.gas_limit; Ok(is_same) diff --git a/src/driver/info.rs b/src/driver/info.rs index d2d7b3b..c53dcad 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -3,52 +3,48 @@ use crate::config::Config; use crate::driver::types::HeadInfo; -use eyre::Result; -use alloy_provider::Provider; +use alloy_provider::{Provider, ReqwestProvider}; use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag}; +use eyre::Result; /// An asynchronous trait for fetching blocks along with their transactions. #[async_trait::async_trait] pub trait InnerProvider { /// Retrieves a block and its transactions - async fn get_block_with_txs( - &self, - block_id: BlockId, - ) -> Result>; + async fn get_block_with_txs(&self, block_id: BlockId) -> Result>; } -/// Wrapper around a [Provider] -pub struct HeadInfoFetcher<'a, P: Provider> { - /// An ethers [Provider] implementing the [JsonRpcClient] trait - inner: &'a P, +/// Wrapper around a [ReqwestProvider]. +pub struct HeadInfoFetcher<'a> { + inner: &'a ReqwestProvider, } -impl<'a, P: Provider> From<&'a P> for HeadInfoFetcher<'a, P> { - /// Converts a [Provider] to a [HeadInfoFetcher] - fn from(inner: &'a P) -> Self { +impl<'a> From<&'a ReqwestProvider> for HeadInfoFetcher<'a> { + /// Converts a [ReqwestProvider] to a [HeadInfoFetcher]. + fn from(inner: &'a ReqwestProvider) -> Self { Self { inner } } } #[async_trait::async_trait] -impl<'a, P: Provider> InnerProvider for HeadInfoFetcher<'a, P> { - /// Fetches a block with transactions - async fn get_block_with_txs( - &self, - block_id: BlockId, - ) -> Result> { - self.inner.get_block(block_id, true).await.map_err(Into::into) +impl<'a> InnerProvider for HeadInfoFetcher<'a> { + /// Fetches a [Block] with transactions. + async fn get_block_with_txs(&self, block_id: BlockId) -> Result> { + self.inner + .get_block(block_id, true) + .await + .map_err(Into::into) } } -/// Provides a method to fetch the latest finalized block +/// Provides a method to fetch the latest finalized [Block]. pub struct HeadInfoQuery {} impl HeadInfoQuery { /// Fetches the latest finalized L2 block - pub async fn get_head_info(p: &P, config: &Config) -> HeadInfo { + pub async fn get_head_info(p: &ReqwestProvider, config: &Config) -> HeadInfo { let parsed_head_info = match p - .get_block_with_txs(BlockId::Number(BlockNumberOrTag::Finalized)) + .get_block(BlockId::Number(BlockNumberOrTag::Finalized), true) .await { Ok(Some(block)) => match HeadInfo::try_from_l2_block(config, block) { @@ -157,10 +153,7 @@ mod test_utils { #[async_trait::async_trait] impl InnerProvider for MockProvider { - async fn get_block_with_txs( - &self, - _: BlockId, - ) -> Result> { + async fn get_block_with_txs(&self, _: BlockId) -> Result> { Ok(self.block.clone()) } } diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 7328df2..2ecd5f4 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -7,7 +7,7 @@ pub mod engine_driver; pub use engine_driver::EngineDriver; pub mod info; -pub use info::{InnerProvider, HeadInfoFetcher, HeadInfoQuery}; +pub use info::{HeadInfoFetcher, HeadInfoQuery, InnerProvider}; pub mod types; pub use types::HeadInfo; diff --git a/src/driver/node_driver.rs b/src/driver/node_driver.rs index dcba681..b6c1eac 100644 --- a/src/driver/node_driver.rs +++ b/src/driver/node_driver.rs @@ -8,7 +8,7 @@ use std::{ }; use alloy_primitives::Address; -use alloy_provider::{ProviderBuilder, Provider}; +use alloy_provider::ProviderBuilder; use eyre::Result; use reqwest::Url; use tokio::{ @@ -27,7 +27,7 @@ use crate::{ telemetry::metrics, }; -use crate::driver::{HeadInfoFetcher, HeadInfoQuery, EngineDriver}; +use crate::driver::{EngineDriver, HeadInfoFetcher, HeadInfoQuery}; /// NodeDriver is responsible for advancing the execution node by feeding /// the derived chain into the engine API @@ -64,9 +64,7 @@ impl NodeDriver { let url = Url::parse(&config.l2_rpc_url)?; let provider = ProviderBuilder::new().on_http(url); - let head = - HeadInfoQuery::get_head_info(&HeadInfoFetcher::from(&provider), &config) - .await; + let head = HeadInfoQuery::get_head_info(&HeadInfoFetcher::from(&provider), &config).await; let finalized_head = head.l2_block_info; let finalized_epoch = head.l1_epoch; @@ -361,7 +359,8 @@ fn get_l1_start_block(epoch_number: u64, channel_timeout: u64) -> u64 { mod tests { use std::{path::PathBuf, str::FromStr}; - use alloy_rpc_types::{BlockId, BlockNumberOrTag}; + use alloy_provider::Provider; + use alloy_rpc_types::{BlockId, BlockNumberOrTag}; use eyre::Result; use tokio::sync::watch::channel; diff --git a/src/driver/types.rs b/src/driver/types.rs index 5ba471c..8cc9d52 100644 --- a/src/driver/types.rs +++ b/src/driver/types.rs @@ -1,7 +1,7 @@ //! A module to handle conversions to a [HeadInfo] struct. +use alloy_rpc_types::{Block, BlockTransactions}; use eyre::Result; -use alloy_rpc_types::{BlockTransactions, Block}; use serde::{Deserialize, Serialize}; use crate::{ @@ -88,10 +88,10 @@ impl HeadInfo { mod tests { mod head_info_bedrock { use crate::driver::HeadInfo; - use eyre::Result; - use alloy_provider::{Provider, ProviderBuilder}; use alloy_primitives::b256; + use alloy_provider::{Provider, ProviderBuilder}; use alloy_rpc_types::Block; + use eyre::Result; #[test] fn should_fail_conversion_from_a_block_to_head_info_if_missing_l1_deposited_tx( @@ -227,7 +227,8 @@ mod tests { eyre::bail!("L2_TEST_RPC_URL is not set"); }; - let l2_block_hash = b256!("75d4a658d7b6430c874c5518752a8d90fb1503eccd6ae4cfc97fd4aedeebb939"); + let l2_block_hash = + b256!("75d4a658d7b6430c874c5518752a8d90fb1503eccd6ae4cfc97fd4aedeebb939"); let expected_l2_block_number = 8428108; let expected_l2_block_timestamp = 1682284284; @@ -240,7 +241,10 @@ mod tests { let l2_rpc_url = reqwest::Url::parse(&l2_rpc_url)?; let l2_provider = ProviderBuilder::new().on_http(l2_rpc_url); - let l2_block = l2_provider.get_block(l2_block_hash.into(), true).await?.unwrap(); + let l2_block = l2_provider + .get_block(l2_block_hash.into(), true) + .await? + .unwrap(); let head = HeadInfo::try_from_bedrock_block(l2_block)?; let HeadInfo { @@ -264,9 +268,9 @@ mod tests { mod head_info_ecotone { use crate::driver::HeadInfo; - use eyre::Result; - use alloy_provider::{Provider, ProviderBuilder}; use alloy_primitives::b256; + use alloy_provider::{Provider, ProviderBuilder}; + use eyre::Result; #[tokio::test] async fn test_head_info_from_l2_block_hash() -> Result<()> { @@ -277,7 +281,8 @@ mod tests { eyre::bail!("L2_TEST_RPC_URL is not set"); }; - let l2_block_hash = b256!("bdd36f0c7ec8e17647dac2780130a842c47dba0025387e80408c161fdb115412"); + let l2_block_hash = + b256!("bdd36f0c7ec8e17647dac2780130a842c47dba0025387e80408c161fdb115412"); let expected_l2_block_number = 21564471; let expected_l2_block_timestamp = 1708557010; @@ -290,7 +295,10 @@ mod tests { let l2_rpc_url = reqwest::Url::parse(&l2_rpc_url)?; let l2_provider = ProviderBuilder::new().on_http(l2_rpc_url); - let l2_block = l2_provider.get_block(l2_block_hash.into(), true).await?.unwrap(); + let l2_block = l2_provider + .get_block(l2_block_hash.into(), true) + .await? + .unwrap(); let head = HeadInfo::try_from_ecotone_block(l2_block)?; let HeadInfo { diff --git a/src/runner/mod.rs b/src/runner/mod.rs index abd877a..5539123 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -13,7 +13,7 @@ use tokio::{ use crate::{ config::{Config, SyncMode, SystemAccounts}, - driver::Driver, + driver::NodeDriver, engine::{Engine, EngineApi, ExecutionPayload, ForkchoiceState, Status}, }; @@ -217,7 +217,7 @@ impl Runner { /// Creates and starts the [Driver] which handles the derivation sync process. async fn start_driver(&self) -> Result<()> { let mut driver = - Driver::from_config(self.config.clone(), self.shutdown_recv.clone()).await?; + NodeDriver::from_config(self.config.clone(), self.shutdown_recv.clone()).await?; if let Err(err) = driver.start().await { tracing::error!("driver failure: {}", err); From eed1d23a46d34db184d2e8e7345991b54571e519 Mon Sep 17 00:00:00 2001 From: refcell Date: Thu, 2 May 2024 05:47:09 -0700 Subject: [PATCH 4/5] fixes --- Cargo.lock | 1479 +-------------------- Cargo.toml | 5 +- src/common/mod.rs | 2 + src/config/mod.rs | 7 +- src/derive/ecotone_upgrade.rs | 4 +- src/derive/mod.rs | 2 +- src/derive/pipeline.rs | 154 +-- src/derive/stages/attributes.rs | 164 ++- src/derive/stages/batcher_transactions.rs | 2 +- src/derive/stages/batches.rs | 7 +- src/derive/stages/block_input.rs | 6 +- src/derive/stages/channels.rs | 2 + src/derive/stages/mod.rs | 20 +- src/derive/stages/single_batch.rs | 2 + src/derive/stages/span_batch.rs | 17 +- src/derive/state.rs | 10 +- src/driver/info.rs | 10 +- src/driver/mod.rs | 2 +- src/engine/api.rs | 4 +- src/engine/auth.rs | 2 - src/engine/fork.rs | 2 + src/engine/mock_engine.rs | 2 + src/engine/mod.rs | 42 +- src/engine/{types.rs => params.rs} | 2 + src/engine/payload.rs | 2 + src/engine/traits.rs | 2 + src/l1/blob_encoding.rs | 2 + src/l1/blob_fetcher.rs | 2 + src/l1/chain_watcher.rs | 10 +- src/l1/config_updates.rs | 2 + src/l1/l1_info.rs | 2 + src/l1/mod.rs | 11 +- src/lib.rs | 34 +- src/network/handlers/block_handler.rs | 2 + src/network/handlers/mod.rs | 4 +- src/network/mod.rs | 9 +- src/network/service/mod.rs | 2 + src/rpc/mod.rs | 2 + src/runner/mod.rs | 2 + src/telemetry/logging.rs | 10 +- src/telemetry/metrics.rs | 2 + src/telemetry/mod.rs | 20 +- src/version/mod.rs | 4 +- 43 files changed, 396 insertions(+), 1677 deletions(-) rename src/engine/{types.rs => params.rs} (97%) diff --git a/Cargo.lock b/Cargo.lock index f6ead8e..d0548e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,16 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "addr2line" version = "0.21.0" @@ -612,15 +602,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - [[package]] name = "asn1-rs" version = "0.5.2" @@ -729,17 +710,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - [[package]] name = "asynchronous-codec" version = "0.6.2" @@ -847,12 +817,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - [[package]] name = "beef" version = "0.5.2" @@ -946,16 +910,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -[[package]] -name = "bs58" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" -dependencies = [ - "sha2 0.10.8", - "tinyvec", -] - [[package]] name = "bstr" version = "1.9.0" @@ -999,27 +953,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "c-kzg" version = "1.0.0" @@ -1034,45 +967,12 @@ dependencies = [ "serde", ] -[[package]] -name = "camino" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" -dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.21", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ - "jobserver", "libc", ] @@ -1185,58 +1085,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "coins-bip32" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" -dependencies = [ - "bs58 0.5.0", - "coins-core", - "digest 0.10.7", - "hmac 0.12.1", - "k256 0.13.3", - "serde", - "sha2 0.10.8", - "thiserror", -] - -[[package]] -name = "coins-bip39" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" -dependencies = [ - "bitvec", - "coins-bip32", - "hmac 0.12.1", - "once_cell", - "pbkdf2 0.12.2", - "rand 0.8.5", - "sha2 0.10.8", - "thiserror", -] - -[[package]] -name = "coins-core" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" -dependencies = [ - "base64 0.21.7", - "bech32", - "bs58 0.5.0", - "digest 0.10.7", - "generic-array", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2 0.10.8", - "sha3", - "thiserror", -] - [[package]] name = "concurrent-queue" version = "2.4.0" @@ -1265,12 +1113,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "convert_case" version = "0.4.0" @@ -1329,25 +1171,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -1590,12 +1413,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - [[package]] name = "digest" version = "0.9.0" @@ -1623,26 +1440,7 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "dirs-sys 0.3.7", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", + "dirs-sys", ] [[package]] @@ -1656,29 +1454,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "discv5" version = "0.2.2" @@ -1689,7 +1464,7 @@ dependencies = [ "aes-gcm 0.9.4", "arrayvec", "delay_map", - "enr 0.7.0", + "enr", "fnv", "futures", "hashlink", @@ -1854,15 +1629,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ena" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" -dependencies = [ - "log", -] - [[package]] name = "encoding_rs" version = "0.8.33" @@ -1879,7 +1645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "492a7e5fc2504d5fdce8e124d3e263b244a68b283cac67a69eda0cd43e0aebad" dependencies = [ "base64 0.13.1", - "bs58 0.4.0", + "bs58", "bytes", "ed25519-dalek 1.0.1", "hex", @@ -1892,24 +1658,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "enr" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" -dependencies = [ - "base64 0.21.7", - "bytes", - "hex", - "k256 0.13.3", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3", - "zeroize", -] - [[package]] name = "enum-as-inner" version = "0.5.1" @@ -1939,394 +1687,76 @@ dependencies = [ ] [[package]] -name = "eth-keystore" -version = "0.5.0" +name = "event-listener" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ - "aes 0.8.3", - "ctr 0.9.2", - "digest 0.10.7", - "hex", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "rand 0.8.5", - "scrypt", - "serde", - "serde_json", - "sha2 0.10.8", - "sha3", - "thiserror", - "uuid 0.8.2", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "ethabi" -version = "18.0.0" +name = "event-listener-strategy" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror", - "uint", + "event-listener", + "pin-project-lite", ] [[package]] -name = "ethbloom" -version = "0.13.0" +name = "eyre" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", + "indenter", + "once_cell", ] [[package]] -name = "ethereum-types" -version = "0.14.1" +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fastrlp" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", + "arrayvec", + "auto_impl", + "bytes", ] [[package]] -name = "ethers" -version = "2.0.14" +name = "ff" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816841ea989f0c69e459af1cf23a6b0033b19a55424a1ea3a30099becdb8dec0" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "ethers-addressbook", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-middleware", - "ethers-providers", - "ethers-signers", - "ethers-solc", + "rand_core 0.6.4", + "subtle", ] [[package]] -name = "ethers-addressbook" -version = "2.0.14" +name = "ff" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5495afd16b4faa556c3bba1f21b98b4983e53c1755022377051a975c3b021759" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "ethers-core", - "once_cell", - "serde", - "serde_json", + "rand_core 0.6.4", + "subtle", ] [[package]] -name = "ethers-contract" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fceafa3578c836eeb874af87abacfb041f92b4da0a78a5edd042564b8ecdaaa" -dependencies = [ - "const-hex", - "ethers-contract-abigen", - "ethers-contract-derive", - "ethers-core", - "ethers-providers", - "futures-util", - "once_cell", - "pin-project", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "ethers-contract-abigen" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ba01fbc2331a38c429eb95d4a570166781f14290ef9fdb144278a90b5a739b" -dependencies = [ - "Inflector", - "const-hex", - "dunce", - "ethers-core", - "ethers-etherscan", - "eyre", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "reqwest 0.11.24", - "serde", - "serde_json", - "syn 2.0.48", - "toml 0.8.10", - "walkdir", -] - -[[package]] -name = "ethers-contract-derive" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87689dcabc0051cde10caaade298f9e9093d65f6125c14575db3fd8c669a168f" -dependencies = [ - "Inflector", - "const-hex", - "ethers-contract-abigen", - "ethers-core", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.48", -] - -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec", - "bytes", - "cargo_metadata", - "chrono", - "const-hex", - "elliptic-curve 0.13.8", - "ethabi", - "generic-array", - "k256 0.13.3", - "num_enum", - "once_cell", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum", - "syn 2.0.48", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "ethers-etherscan" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79e5973c26d4baf0ce55520bd732314328cabe53193286671b47144145b9649" -dependencies = [ - "chrono", - "ethers-core", - "reqwest 0.11.24", - "semver 1.0.21", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "ethers-middleware" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f9fdf09aec667c099909d91908d5eaf9be1bd0e2500ba4172c1d28bfaa43de" -dependencies = [ - "async-trait", - "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-providers", - "ethers-signers", - "futures-channel", - "futures-locks", - "futures-util", - "instant", - "reqwest 0.11.24", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-futures", - "url", -] - -[[package]] -name = "ethers-providers" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" -dependencies = [ - "async-trait", - "auto_impl", - "base64 0.21.7", - "bytes", - "const-hex", - "enr 0.10.0", - "ethers-core", - "futures-core", - "futures-timer 3.0.2", - "futures-util", - "hashers", - "http 0.2.11", - "instant", - "jsonwebtoken", - "once_cell", - "pin-project", - "reqwest 0.11.24", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-tungstenite", - "tracing", - "tracing-futures", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "ws_stream_wasm", -] - -[[package]] -name = "ethers-signers" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228875491c782ad851773b652dd8ecac62cda8571d3bc32a5853644dd26766c2" -dependencies = [ - "async-trait", - "coins-bip32", - "coins-bip39", - "const-hex", - "elliptic-curve 0.13.8", - "eth-keystore", - "ethers-core", - "rand 0.8.5", - "sha2 0.10.8", - "thiserror", - "tracing", -] - -[[package]] -name = "ethers-solc" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66244a771d9163282646dbeffe0e6eca4dda4146b6498644e678ac6089b11edd" -dependencies = [ - "cfg-if", - "const-hex", - "dirs 5.0.1", - "dunce", - "ethers-core", - "glob", - "home", - "md-5", - "num_cpus", - "once_cell", - "path-slash", - "rayon", - "regex", - "semver 1.0.21", - "serde", - "serde_json", - "solang-parser", - "svm-rs", - "thiserror", - "tiny-keccak", - "tokio", - "tracing", - "walkdir", - "yansi 0.5.1", -] - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.6" +name = "fiat-crypto" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" @@ -2356,22 +1786,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "fnv" version = "1.0.7" @@ -2402,16 +1816,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "funty" version = "2.0.0" @@ -2510,16 +1914,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "futures-locks" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" -dependencies = [ - "futures-channel", - "futures-task", -] - [[package]] name = "futures-macro" version = "0.3.30" @@ -2552,7 +1946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" dependencies = [ "futures-io", - "rustls 0.20.9", + "rustls", "webpki", ] @@ -2589,10 +1983,6 @@ name = "futures-timer" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" -dependencies = [ - "gloo-timers", - "send_wrapper 0.4.0", -] [[package]] name = "futures-util" @@ -2633,15 +2023,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -2716,20 +2097,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.5", - "regex-syntax 0.8.2", -] - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -2801,15 +2170,6 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "hashers" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" -dependencies = [ - "fxhash", -] - [[package]] name = "hashlink" version = "0.7.0" @@ -2906,15 +2266,6 @@ dependencies = [ "hmac 0.8.1", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "hostname" version = "0.3.1" @@ -3037,20 +2388,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.11", - "hyper 0.14.28", - "rustls 0.21.10", - "tokio", - "tokio-rustls", -] - [[package]] name = "hyper-tls" version = "0.5.0" @@ -3182,24 +2519,6 @@ dependencies = [ "parity-scale-codec", ] -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -3279,17 +2598,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "is-terminal" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" -dependencies = [ - "hermit-abi 0.3.5", - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "itertools" version = "0.10.5" @@ -3299,15 +2607,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.12.1" @@ -3323,15 +2622,6 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" -[[package]] -name = "jobserver" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.68" @@ -3462,7 +2752,6 @@ dependencies = [ "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", - "signature 2.2.0", ] [[package]] @@ -3484,34 +2773,6 @@ dependencies = [ "sha3-asm", ] -[[package]] -name = "lalrpop" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" -dependencies = [ - "ascii-canvas", - "bit-set", - "diff", - "ena", - "is-terminal", - "itertools 0.10.5", - "lalrpop-util", - "petgraph", - "regex", - "regex-syntax 0.7.5", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" - [[package]] name = "lazy_static" version = "1.4.0" @@ -3684,7 +2945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "asn1_der", - "bs58 0.4.0", + "bs58", "ed25519-dalek 2.1.1", "libsecp256k1", "log", @@ -3806,7 +3067,7 @@ dependencies = [ "parking_lot 0.12.1", "quinn-proto", "rand 0.8.5", - "rustls 0.20.9", + "rustls", "thiserror", "tokio", ] @@ -3871,7 +3132,7 @@ dependencies = [ "libp2p-identity", "rcgen", "ring 0.16.20", - "rustls 0.20.9", + "rustls", "thiserror", "webpki", "x509-parser", @@ -4009,9 +3270,8 @@ dependencies = [ "chrono", "clap", "ctrlc", - "dirs 4.0.0", + "dirs", "discv5", - "ethers", "eyre", "figment", "futures", @@ -4037,7 +3297,7 @@ dependencies = [ "tracing-appender", "tracing-subscriber", "unsigned-varint", - "uuid 1.7.0", + "uuid", ] [[package]] @@ -4061,16 +3321,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - [[package]] name = "memchr" version = "2.7.1" @@ -4268,12 +3518,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - [[package]] name = "nix" version = "0.24.3" @@ -4368,27 +3612,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "object" version = "0.32.2" @@ -4419,31 +3642,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "openssl" version = "0.10.63" @@ -4498,12 +3696,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - [[package]] name = "os_str_bytes" version = "6.6.1" @@ -4596,51 +3788,12 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "paste" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" -[[package]] -name = "path-slash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", - "password-hash", - "sha2 0.10.8", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", -] - [[package]] name = "pear" version = "0.2.8" @@ -4649,7 +3802,7 @@ checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" dependencies = [ "inlinable_string", "pear_codegen", - "yansi 1.0.0-rc.1", + "yansi", ] [[package]] @@ -4690,77 +3843,6 @@ dependencies = [ "ucd-trie", ] -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.2.2", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project" version = "1.1.4" @@ -4886,22 +3968,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "prettyplease" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" -dependencies = [ - "proc-macro2", - "syn 2.0.48", -] - [[package]] name = "primitive-types" version = "0.12.2" @@ -4910,9 +3976,6 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", "uint", ] @@ -4935,15 +3998,6 @@ dependencies = [ "toml_edit 0.20.7", ] -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -4987,7 +4041,7 @@ dependencies = [ "quote", "syn 2.0.48", "version_check", - "yansi 1.0.0-rc.1", + "yansi", ] [[package]] @@ -5099,7 +4153,7 @@ dependencies = [ "rand 0.8.5", "ring 0.16.20", "rustc-hash", - "rustls 0.20.9", + "rustls", "slab", "thiserror", "tinyvec", @@ -5202,26 +4256,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rayon" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "rcgen" version = "0.10.0" @@ -5301,12 +4335,6 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - [[package]] name = "regex-syntax" version = "0.8.2" @@ -5328,7 +4356,6 @@ dependencies = [ "http 0.2.11", "http-body 0.4.6", "hyper 0.14.28", - "hyper-rustls", "hyper-tls 0.5.0", "ipnet", "js-sys", @@ -5338,7 +4365,6 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -5347,13 +4373,11 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg 0.50.0", ] @@ -5456,15 +4480,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "rle-decode-fast" version = "1.0.3" @@ -5473,24 +4488,12 @@ checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" [[package]] name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "bytes", + "rustc-hex", ] [[package]] @@ -5608,18 +4611,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring 0.17.7", - "rustls-webpki", - "sct", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -5645,22 +4636,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - [[package]] name = "rusty-fork" version = "0.3.0" @@ -5690,48 +4665,6 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher 0.4.4", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scale-info" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" -dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" -dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "schannel" version = "0.1.23" @@ -5747,18 +4680,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scrypt" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" -dependencies = [ - "hmac 0.12.1", - "pbkdf2 0.11.0", - "salsa20", - "sha2 0.10.8", -] - [[package]] name = "sct" version = "0.7.1" @@ -5834,9 +4755,6 @@ name = "semver" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" -dependencies = [ - "serde", -] [[package]] name = "semver-parser" @@ -5847,18 +4765,6 @@ dependencies = [ "pest", ] -[[package]] -name = "send_wrapper" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - [[package]] name = "serde" version = "1.0.196" @@ -5924,17 +4830,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha2" version = "0.9.9" @@ -6029,12 +4924,6 @@ dependencies = [ "time", ] -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "slab" version = "0.4.9" @@ -6109,20 +4998,6 @@ dependencies = [ "sha-1", ] -[[package]] -name = "solang-parser" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" -dependencies = [ - "itertools 0.11.0", - "lalrpop", - "lalrpop-util", - "phf", - "thiserror", - "unicode-xid", -] - [[package]] name = "spin" version = "0.5.2" @@ -6187,73 +5062,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.1", - "phf_shared 0.10.0", - "precomputed-hash", -] - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.48", -] - [[package]] name = "subtle" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "svm-rs" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" -dependencies = [ - "dirs 5.0.1", - "fs2", - "hex", - "once_cell", - "reqwest 0.11.24", - "semver 1.0.21", - "serde", - "serde_json", - "sha2 0.10.8", - "thiserror", - "url", - "zip", -] - [[package]] name = "syn" version = "1.0.109" @@ -6345,17 +5165,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -6518,16 +5327,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.10", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.14" @@ -6540,21 +5339,6 @@ dependencies = [ "tokio-util 0.7.10", ] -[[package]] -name = "tokio-tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "rustls 0.21.10", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", -] - [[package]] name = "tokio-util" version = "0.6.10" @@ -6627,17 +5411,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.2", - "toml_datetime", - "winnow", -] - [[package]] name = "toml_edit" version = "0.22.4" @@ -6724,16 +5497,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -6815,26 +5578,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 0.2.11", - "httparse", - "log", - "rand 0.8.5", - "rustls 0.21.10", - "sha1", - "thiserror", - "url", - "utf-8", -] - [[package]] name = "typenum" version = "1.17.0" @@ -6954,22 +5697,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom 0.2.12", - "serde", -] - [[package]] name = "uuid" version = "1.7.0" @@ -7012,16 +5739,6 @@ dependencies = [ "libc", ] -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -7144,12 +5861,6 @@ dependencies = [ "untrusted 0.9.0", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "widestring" version = "1.0.2" @@ -7376,25 +6087,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ws_stream_wasm" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" -dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version 0.4.0", - "send_wrapper 0.6.0", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "wyz" version = "0.5.1" @@ -7433,12 +6125,6 @@ dependencies = [ "time", ] -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - [[package]] name = "yansi" version = "1.0.0-rc.1" @@ -7493,52 +6179,3 @@ dependencies = [ "quote", "syn 2.0.48", ] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes 0.8.3", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "sha1", - "time", - "zstd", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml index 837799b..b4e2f85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ path = "./bin/network.rs" tokio = { version = "1.28.0", features = ["full"] } async-trait = "0.1.73" eyre = "0.6.8" -ethers = { version = "2.0.14", features = ["optimism"] } hex = "0.4.3" libflate = "1.2.0" openssl = { version = "0.10", features = ["vendored"] } @@ -30,7 +29,7 @@ again = "0.1" # Alloy types alloy-rlp = { version = "0.3", default-features = false } alloy-primitives = { version = "0.7.1", default-features = false, features = ["serde"] } -alloy-provider = { git = "https://github.com/alloy-rs/alloy" } +alloy-provider = { git = "https://github.com/alloy-rs/alloy", features = [ "reqwest" ] } alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy" } alloy-consensus = { git = "https://github.com/alloy-rs/alloy" } alloy-eips = { git = "https://github.com/alloy-rs/alloy" } @@ -56,7 +55,7 @@ serde_json = "1.0.93" # Backend Crates uuid = { version = "1.3.0", features = ["v4"] } bytes = "1.4.0" -reqwest = "0.11.14" +reqwest = { version = "0.11.14", features = ["json"] } jsonwebtoken = "8.2.0" rand = "0.8.5" diff --git a/src/common/mod.rs b/src/common/mod.rs index e4407a4..4285d2a 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,3 +1,5 @@ +//! Module containing common types and functions used throughout the crate. + use std::fmt::Debug; use alloy_primitives::B256; diff --git a/src/config/mod.rs b/src/config/mod.rs index a8149cc..ecd54cb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,4 +1,4 @@ -use std::{fmt, iter, path::PathBuf, process::exit, str::FromStr}; +//! Module contains Configuration types. use alloy_primitives::{Address, B256, U256, U64}; use figment::{ @@ -6,10 +6,11 @@ use figment::{ Figment, }; use serde::{Deserialize, Serialize}; +use std::{fmt, iter, path::PathBuf, process::exit, str::FromStr}; use crate::common::{BlockInfo, Epoch}; -/// Sync Mode Specifies how `magi` should sync the L2 chain +/// Sync Mode Specifies how to sync the L2 chain #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] pub enum SyncMode { /// Fast sync mode @@ -47,7 +48,7 @@ impl fmt::Display for SyncMode { } } -/// The global `Magi` configuration. +/// The global configuration. #[derive(Debug, Clone, Deserialize, Default)] pub struct Config { /// The L1 chain RPC URL diff --git a/src/derive/ecotone_upgrade.rs b/src/derive/ecotone_upgrade.rs index e204e01..831952e 100644 --- a/src/derive/ecotone_upgrade.rs +++ b/src/derive/ecotone_upgrade.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use alloy_consensus::TxEnvelope; -use alloy_primitives::{Address, b256, address, uint, Bytes, U256, U64}; +use alloy_primitives::{address, b256, uint, Address, Bytes, U256, U64}; use crate::common::RawTransaction; @@ -60,7 +60,7 @@ pub fn get_ecotone_upgrade_transactions() -> Vec { let update_l1_block_proxy = Transaction { transaction_type: Some(U64::from(0x7E)), source_hash: b256!("18acb38c5ff1c238a7460ebc1b421fa49ec4874bdf1e0a530d234104e5e67dbc") - .unwrap(), + .unwrap(), from: address!("0000000000000000000000000000000000000000"), to: Some(address!("4200000000000000000000000000000000000015")), mint: None, diff --git a/src/derive/mod.rs b/src/derive/mod.rs index e880990..667a05e 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -1,4 +1,4 @@ -//! The `derive` module contains the stages and orchestration for the derivation pipeline. +//! This module contains the stages and orchestration for the derivation pipeline. pub mod stages; diff --git a/src/derive/pipeline.rs b/src/derive/pipeline.rs index cc45c8b..c9638c0 100644 --- a/src/derive/pipeline.rs +++ b/src/derive/pipeline.rs @@ -1,12 +1,13 @@ //! Contains the pipeline implementation. -use std::sync::{mpsc, Arc, RwLock}; use alloy_primitives::Bytes; use eyre::Result; +use std::sync::{mpsc, Arc, RwLock}; use crate::{config::Config, engine::PayloadAttributes}; use crate::derive::{ + purgeable::PurgeableIterator, stages::{ attributes::Attributes, batcher_transactions::{BatcherTransactionMessage, BatcherTransactions}, @@ -14,7 +15,6 @@ use crate::derive::{ channels::Channels, }, state::State, - purgeable::PurgeableIterator, }; /// The derivation pipeline is iterated on to update attributes for new blocks. @@ -58,11 +58,7 @@ impl Pipeline { } /// Sends [BatcherTransactions] & the L1 block they were received in to the [BatcherTransactions] receiver. - pub fn push_batcher_transactions( - &self, - txs: Vec, - l1_origin: u64, - ) -> Result<()> { + pub fn push_batcher_transactions(&self, txs: Vec, l1_origin: u64) -> Result<()> { let txs = txs.into_iter().map(Bytes::from).collect(); self.batcher_transaction_sender .send(BatcherTransactionMessage { txs, l1_origin })?; @@ -94,100 +90,106 @@ mod tests { sync::{Arc, RwLock}, }; - use ethers::{ - providers::{Middleware, Provider}, - types::H256, - utils::keccak256, - }; - use crate::{ common::RawTransaction, config::{ChainConfig, Config}, derive::*, l1::{BlockUpdate, ChainWatcher}, }; + use alloy_primitives::{keccak256, B256}; + use alloy_provider::{Provider, ProviderBuilder, ReqwestProvider}; + use alloy_rpc_types::BlockTransactions; #[tokio::test(flavor = "multi_thread")] async fn test_attributes_match() { - if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() { - let rpc = env::var("L1_TEST_RPC_URL").unwrap(); - let l2_rpc = env::var("L2_TEST_RPC_URL").unwrap(); - - let config = Arc::new(Config { - l1_rpc_url: rpc.to_string(), - l1_beacon_url: String::new(), - l2_rpc_url: l2_rpc.to_string(), - chain: ChainConfig::optimism_goerli(), - l2_engine_url: String::new(), - jwt_secret: String::new(), - checkpoint_sync_url: None, - rpc_port: 9545, - rpc_addr: "127.0.0.1".to_string(), - devnet: false, - }); - - let mut chain_watcher = ChainWatcher::new( - config.chain.l1_start_epoch.number, - config.chain.l2_genesis.number, + if !std::env::var("L1_TEST_RPC_URL").is_ok() { + return; + } + if !std::env::var("L2_TEST_RPC_URL").is_ok() { + return; + } + + let rpc = env::var("L1_TEST_RPC_URL").unwrap(); + let l2_rpc = env::var("L2_TEST_RPC_URL").unwrap(); + + let config = Arc::new(Config { + l1_rpc_url: rpc.to_string(), + l1_beacon_url: String::new(), + l2_rpc_url: l2_rpc.to_string(), + chain: ChainConfig::optimism_goerli(), + l2_engine_url: String::new(), + jwt_secret: String::new(), + checkpoint_sync_url: None, + rpc_port: 9545, + rpc_addr: "127.0.0.1".to_string(), + devnet: false, + }); + + let mut chain_watcher = ChainWatcher::new( + config.chain.l1_start_epoch.number, + config.chain.l2_genesis.number, + config.clone(), + ) + .unwrap(); + + chain_watcher.start().unwrap(); + + let rpc_url = reqwest::Url::parse(&env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); + let provider = ProviderBuilder::default().on_http(rpc_url); + let state = Arc::new(RwLock::new( + State::new( + config.chain.l2_genesis, + config.chain.l1_start_epoch, + &provider, config.clone(), ) - .unwrap(); - - chain_watcher.start().unwrap(); - - let provider = Provider::try_from(env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); - let state = Arc::new(RwLock::new( - State::new( - config.chain.l2_genesis, - config.chain.l1_start_epoch, - &provider, - config.clone(), - ) - .await, - )); + .await, + )); - let mut pipeline = Pipeline::new(state.clone(), config.clone(), 0).unwrap(); + let mut pipeline = Pipeline::new(state.clone(), config.clone(), 0).unwrap(); - chain_watcher.recv_from_channel().await.unwrap(); - let update = chain_watcher.recv_from_channel().await.unwrap(); + chain_watcher.recv_from_channel().await.unwrap(); + let update = chain_watcher.recv_from_channel().await.unwrap(); - let l1_info = match update { - BlockUpdate::NewBlock(block) => *block, - _ => panic!("wrong update type"), - }; + let l1_info = match update { + BlockUpdate::NewBlock(block) => *block, + _ => panic!("wrong update type"), + }; - pipeline - .push_batcher_transactions( - l1_info.batcher_transactions.clone(), - l1_info.block_info.number, - ) - .unwrap(); + pipeline + .push_batcher_transactions( + l1_info.batcher_transactions.clone(), + l1_info.block_info.number, + ) + .unwrap(); - state.write().unwrap().update_l1_info(l1_info); + state.write().unwrap().update_l1_info(l1_info); - if let Some(payload) = pipeline.next() { - let hashes = get_tx_hashes(&payload.transactions.unwrap()); - let expected_hashes = get_expected_hashes(config.chain.l2_genesis.number + 1).await; + if let Some(payload) = pipeline.next() { + let hashes = get_tx_hashes(&payload.transactions.unwrap()); + let expected_hashes = get_expected_hashes(config.chain.l2_genesis.number + 1).await; - assert_eq!(hashes, expected_hashes); - } + assert_eq!(hashes, expected_hashes); } } - async fn get_expected_hashes(block_num: u64) -> Vec { - let provider = Provider::try_from(env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); - - provider - .get_block(block_num) + async fn get_expected_hashes(block_num: u64) -> Vec { + let rpc_url = reqwest::Url::parse(&env::var("L2_TEST_RPC_URL").unwrap()).unwrap(); + let provider: ReqwestProvider = ProviderBuilder::default().on_http(rpc_url); + let mut txs = provider + .get_block(block_num.into(), true) .await .unwrap() .unwrap() - .transactions + .transactions; + txs.convert_to_hashes(); + let BlockTransactions::Hashes(hashes) = txs else { + panic!("failed to get expected hashes") + }; + hashes } - fn get_tx_hashes(txs: &[RawTransaction]) -> Vec { - txs.iter() - .map(|tx| H256::from_slice(&keccak256(&tx.0))) - .collect() + fn get_tx_hashes(txs: &[RawTransaction]) -> Vec { + txs.iter().map(|tx| keccak256(&tx.0)).collect() } } diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 6a46dcb..a684f77 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -2,10 +2,9 @@ use std::sync::{Arc, RwLock}; +use alloy_primitives::{keccak256, Address, Bytes, B256, U256, U64}; +use alloy_rlp::encode; use alloy_rlp::Encodable; -use alloy_primitives::{Address, B256, keccak256, U64, U256}; - -use ethers::abi::{decode, encode, ParamType, Token}; use eyre::Result; @@ -19,6 +18,7 @@ use crate::l1::L1Info; use super::block_input::BlockInput; /// Represents the `Payload Attributes Derivation` stage. +#[derive(Debug)] pub struct Attributes { /// An iterator over [BlockInput]: used to derive [PayloadAttributes] block_input_iter: Box>>, @@ -49,8 +49,7 @@ impl PurgeableIterator for Attributes { fn purge(&mut self) { self.block_input_iter.purge(); self.sequence_number = 0; - self.epoch_hash = - self.state.read().unwrap().safe_epoch.hash; + self.epoch_hash = self.state.read().unwrap().safe_epoch.hash; } } @@ -276,37 +275,37 @@ impl From for DepositedTransaction { } } -impl Encodable for DepositedTransaction { - fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { - out.put(&[0x7E]); - out.put_u8(8); // Start the list - - out.put(&self.source_hash); - - } -} - -impl Encodable for { - /// Converts a [DepositedTransaction] to RLP bytes and appends to the stream. - fn rlp_append(&self, s: &mut RlpStream) { - s.append_raw(&[0x7E], 1); - s.begin_list(8); - s.append(&self.source_hash); - s.append(&self.from); - - if let Some(to) = self.to { - s.append(&to); - } else { - s.append(&""); - } - - s.append(&self.mint); - s.append(&self.value); - s.append(&self.gas); - s.append(&self.is_system_tx); - s.append(&self.data); - } -} +// impl Encodable for DepositedTransaction { +// fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { +// out.put(&[0x7E]); +// out.put_u8(8); // Start the list +// +// out.put(&self.source_hash); +// +// } +// } + +// impl Encodable for { +// /// Converts a [DepositedTransaction] to RLP bytes and appends to the stream. +// fn rlp_append(&self, s: &mut RlpStream) { +// s.append_raw(&[0x7E], 1); +// s.begin_list(8); +// s.append(&self.source_hash); +// s.append(&self.from); +// +// if let Some(to) = self.to { +// s.append(&to); +// } else { +// s.append(&""); +// } +// +// s.append(&self.mint); +// s.append(&self.value); +// s.append(&self.gas); +// s.append(&self.is_system_tx); +// s.append(&self.data); +// } +// } /// Represents the attributes provided as calldata in an attributes deposited transaction. #[derive(Debug)] @@ -358,24 +357,24 @@ impl AttributesDeposited { } } - /// Encodes [AttributesDeposited] into `setL1BlockValues` transaction calldata, including the selector. - fn encode(&self) -> Vec { - let tokens = vec![ - Token::Uint(self.number.into()), - Token::Uint(self.timestamp.into()), - Token::Uint(self.base_fee), - Token::FixedBytes(self.hash.to_vec()), - Token::Uint(self.sequence_number.into()), - Token::FixedBytes(self.batcher_hash.to_vec()), - Token::Uint(self.fee_overhead), - Token::Uint(self.fee_scalar), - ]; - - let selector = hex::decode("015d8eb9").unwrap(); - let data = encode(&tokens); - - [selector, data].concat() - } + // /// Encodes [AttributesDeposited] into `setL1BlockValues` transaction calldata, including the selector. + // fn encode(&self) -> Vec { + // let tokens = vec![ + // Token::Uint(self.number.into()), + // Token::Uint(self.timestamp.into()), + // Token::Uint(self.base_fee), + // Token::FixedBytes(self.hash.to_vec()), + // Token::Uint(self.sequence_number.into()), + // Token::FixedBytes(self.batcher_hash.to_vec()), + // Token::Uint(self.fee_overhead), + // Token::Uint(self.fee_scalar), + // ]; + // + // let selector = hex::decode("015d8eb9").unwrap(); + // let data = encode(&tokens); + // + // [selector, data].concat() + // } } /// Represents a user deposited transaction. @@ -415,10 +414,59 @@ impl TryFrom for UserDeposited { /// Converts the emitted L1 deposit event log into [UserDeposited] fn try_from(log: alloy_rpc_types::Log) -> Result { - let opaque_data = decode(&[ParamType::Bytes], &log.data().data)?[0] - .clone() - .into_bytes() - .unwrap(); + // Solidity serializes the event's Data field as follows: + // + // ```solidity + // abi.encode(abi.encodPacked(uint256 mint, uint256 value, uint64 gasLimit, uint8 isCreation, bytes data)) + // ``` + // + // The the opaqueData will be packed as shown below: + // + // ------------------------------------------------------------ + // | offset | 256 byte content | + // ------------------------------------------------------------ + // | 0 | [0; 24] . {U64 big endian, hex encoded offset} | + // ------------------------------------------------------------ + // | 32 | [0; 24] . {U64 big endian, hex encoded length} | + // ------------------------------------------------------------ + + let opaque_content_offset: U64 = + U64::try_from_be_slice(&log.data.data[24..32]).ok_or(eyre::eyre!( + "Invalid opaque data offset: {}:", + Bytes::copy_from_slice(&log.data.data[24..32]) + ))?; + if opaque_content_offset != U64::from(32) { + eyre::bail!("Invalid opaque data offset: {}", opaque_content_offset); + } + + // The next 32 bytes indicate the length of the opaqueData content. + let opaque_content_len = + u64::from_be_bytes(log.data.data[56..64].try_into().map_err(|_| { + eyre::eyre!( + "Invalid opaque data length: {}", + Bytes::copy_from_slice(&log.data.data[56..64]) + ) + })?); + if opaque_content_len as usize > log.data.data.len() - 64 { + eyre::bail!( + "Invalid opaque data length: {} exceeds log data length: {}", + opaque_content_len, + log.data.data.len() - 64 + ); + } + let padded_len = opaque_content_len + .checked_add(32) + .ok_or(eyre::eyre!("Opaque data overflow: {}", opaque_content_len))?; + if padded_len as usize <= log.data.data.len() - 64 { + eyre::bail!( + "Opaque data with len {} overflows padded length {}", + log.data.data.len() - 64, + opaque_content_len + ); + } + + // The remaining data is the tightly packed and padded to 32 bytes opaqueData + let opaque_data = &log.data.data[64..64 + opaque_content_len as usize]; let from = Address::from_slice(log.topics()[1].as_slice()); let to = Address::from_slice(log.topics()[2].as_slice()); diff --git a/src/derive/stages/batcher_transactions.rs b/src/derive/stages/batcher_transactions.rs index 0e6e85b..8fe08ce 100644 --- a/src/derive/stages/batcher_transactions.rs +++ b/src/derive/stages/batcher_transactions.rs @@ -2,9 +2,9 @@ use std::sync::mpsc; +use alloy_primitives::Bytes; use eyre::Result; use std::collections::VecDeque; -use alloy_primitives::Bytes; use crate::derive::PurgeableIterator; diff --git a/src/derive/stages/batches.rs b/src/derive/stages/batches.rs index 84e0575..fcd75f4 100644 --- a/src/derive/stages/batches.rs +++ b/src/derive/stages/batches.rs @@ -1,7 +1,7 @@ //! A module to handle processing of a [Batch]. -use alloy_rlp::Rlp; use alloy_rlp::Decodable; +use alloy_rlp::Rlp; use core::fmt::Debug; use std::cmp::Ordering; use std::collections::BTreeMap; @@ -437,7 +437,10 @@ fn decode_batches(channel: &Channel, chain_id: u64) -> Result> { match version { 0 => { let rlp = Rlp::new(batch_content); - let size = rlp.get_next::()?.ok_or_else(|| eyre::eyre!("failed to get header"))?.len(); + let size = rlp + .get_next::()? + .ok_or_else(|| eyre::eyre!("failed to get header"))? + .len(); let mut batch = SingleBatch::decode(&mut batch_content)?; batch.l1_inclusion_block = Some(channel.l1_inclusion_block); diff --git a/src/derive/stages/block_input.rs b/src/derive/stages/block_input.rs index 6d982af..3038739 100644 --- a/src/derive/stages/block_input.rs +++ b/src/derive/stages/block_input.rs @@ -1,3 +1,5 @@ +//! Module handles building [BlockInput] from a batch of transactions. + use std::sync::{Arc, RwLock}; use eyre::Result; @@ -7,9 +9,11 @@ use crate::{ derive::state::State, }; -/// A marker trait to allow representing an epoch as either a block number or an [Epoch] +/// A marker trait to allow representing an epoch as either a block number or an [Epoch]. pub trait EpochType {} + impl EpochType for u64 {} + impl EpochType for Epoch {} /// A single L2 block derived from a batch. diff --git a/src/derive/stages/channels.rs b/src/derive/stages/channels.rs index 6492e37..117d431 100644 --- a/src/derive/stages/channels.rs +++ b/src/derive/stages/channels.rs @@ -1,3 +1,5 @@ +//! Module handles channel bank derivation stage. + use std::sync::Arc; use super::batcher_transactions::{BatcherTransaction, Frame}; diff --git a/src/derive/stages/mod.rs b/src/derive/stages/mod.rs index 379317f..1309028 100644 --- a/src/derive/stages/mod.rs +++ b/src/derive/stages/mod.rs @@ -1,22 +1,24 @@ //! A module defining the stages of the derivation pipeline. pub mod attributes; -pub use attributes::{Attributes, DepositedTransaction, AttributesDeposited, UserDeposited}; +pub use attributes::{Attributes, AttributesDeposited, DepositedTransaction, UserDeposited}; pub mod batcher_transactions; -pub use batcher_transactions::{BatcherTransactions, BatcherTransactionMessage, BatcherTransaction, Frame}; +pub use batcher_transactions::{ + BatcherTransaction, BatcherTransactionMessage, BatcherTransactions, Frame, +}; pub mod batches; pub use batches::Batches; -/// A module to handle building a [BlockInput](crate::derive::stages::block_input::BlockInput) -mod block_input; +pub mod block_input; +pub use block_input::{BlockInput, EpochType}; -/// A module to handle the channel bank derivation stage pub mod channels; +pub use channels::{Channel, Channels, PendingChannel}; -/// A module to handle processing of a [SingleBatch](crate::derive::stages::single_batch::SingleBatch) -mod single_batch; +pub mod single_batch; +pub use single_batch::SingleBatch; -/// A module to handle processing of a [SpanBatch](crate::derive::stages::span_batch::SpanBatch) -mod span_batch; +pub mod span_batch; +pub use span_batch::SpanBatch; diff --git a/src/derive/stages/single_batch.rs b/src/derive/stages/single_batch.rs index d613b26..8bb0f70 100644 --- a/src/derive/stages/single_batch.rs +++ b/src/derive/stages/single_batch.rs @@ -1,3 +1,5 @@ +//! Module to handle [SingleBatch] processing. + use alloy_primitives::B256; use alloy_rlp::{RlpDecodable, RlpEncodable}; diff --git a/src/derive/stages/span_batch.rs b/src/derive/stages/span_batch.rs index ddf8166..004ade6 100644 --- a/src/derive/stages/span_batch.rs +++ b/src/derive/stages/span_batch.rs @@ -1,7 +1,7 @@ -use ethers::{ - types::{transaction::eip2930::AccessList, Address, Bytes, U256}, - utils::rlp::{Rlp, RlpStream}, -}; +//! Module to handle [SpanBatch] decoding and processing. + +use alloy_primitives::{Address, Bytes, U256}; +use alloy_rpc_types::transaction::AccessList; use eyre::Result; use crate::{common::RawTransaction, config::Config}; @@ -448,7 +448,7 @@ fn decode_signatures(data: &[u8], tx_count: u64) -> (Vec<(U256, U256)>, &[u8]) { /// Decodes a U256 from an arbitrary slice of bytes fn decode_u256(data: &[u8]) -> (U256, &[u8]) { let (bytes, data) = take_data(data, 32); - let value = U256::from_big_endian(bytes); + let value = U256::from_be_slice(bytes); (value, data) } @@ -456,10 +456,7 @@ fn decode_u256(data: &[u8]) -> (U256, &[u8]) { mod test { use std::io::Read; - use ethers::{ - types::H256, - utils::{keccak256, rlp::Rlp}, - }; + use alloy_primitives::keccak256; use libflate::zlib::Decoder; use crate::{ @@ -522,7 +519,7 @@ mod test { let block_number = (input.timestamp - config.chain.l2_genesis.timestamp) / 2; println!("block: {}, epoch: {}", block_number, input.epoch); input.transactions.iter().for_each(|tx| { - println!("{:?}", H256::from(keccak256(&tx.0))); + println!("{:?}", keccak256(&tx.0)); }); }); diff --git a/src/derive/state.rs b/src/derive/state.rs index 7d6b6e0..6a6ada5 100644 --- a/src/derive/state.rs +++ b/src/derive/state.rs @@ -37,7 +37,7 @@ impl State { pub async fn new( finalized_head: BlockInfo, finalized_epoch: Epoch, - provider: &dyn Provider, + provider: &impl Provider, config: Arc, ) -> Self { let l2_refs = l2_refs(finalized_head.number, provider, &config).await; @@ -97,10 +97,8 @@ impl State { /// This also updates ``current_epoch_num`` to the block number of the given ``l1_info``. pub fn update_l1_info(&mut self, l1_info: L1Info) { self.current_epoch_num = l1_info.block_info.number; - self.l1_hashes.insert( - l1_info.block_info.number, - l1_info.block_info.hash, - ); + self.l1_hashes + .insert(l1_info.block_info.number, l1_info.block_info.hash); self.l1_info.insert(l1_info.block_info.hash, l1_info); self.prune(); } @@ -165,7 +163,7 @@ impl State { /// If the lookback period is before the genesis block, it will return L2 blocks starting from genesis. async fn l2_refs( head_num: u64, - provider: &dyn Provider, + provider: &impl Provider, config: &Config, ) -> BTreeMap { let lookback = config.chain.max_seq_drift / config.chain.blocktime; diff --git a/src/driver/info.rs b/src/driver/info.rs index c53dcad..fa583a2 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -3,7 +3,7 @@ use crate::config::Config; use crate::driver::types::HeadInfo; -use alloy_provider::{Provider, ReqwestProvider}; +use alloy_provider::Provider; use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag}; use eyre::Result; @@ -16,12 +16,12 @@ pub trait InnerProvider { /// Wrapper around a [ReqwestProvider]. pub struct HeadInfoFetcher<'a> { - inner: &'a ReqwestProvider, + inner: &'a dyn Provider, } -impl<'a> From<&'a ReqwestProvider> for HeadInfoFetcher<'a> { +impl<'a> From<&'a dyn Provider> for HeadInfoFetcher<'a> { /// Converts a [ReqwestProvider] to a [HeadInfoFetcher]. - fn from(inner: &'a ReqwestProvider) -> Self { + fn from(inner: &'a dyn Provider) -> Self { Self { inner } } } @@ -42,7 +42,7 @@ pub struct HeadInfoQuery {} impl HeadInfoQuery { /// Fetches the latest finalized L2 block - pub async fn get_head_info(p: &ReqwestProvider, config: &Config) -> HeadInfo { + pub async fn get_head_info(p: impl Provider, config: &Config) -> HeadInfo { let parsed_head_info = match p .get_block(BlockId::Number(BlockNumberOrTag::Finalized), true) .await diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 2ecd5f4..fbfcfb7 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -1,4 +1,4 @@ -//! Contains Drivers for interfacing with the rollup node. +//! Contains drivers that drive the execution client using the **L2** Engine API. pub mod node_driver; pub use node_driver::NodeDriver; diff --git a/src/engine/api.rs b/src/engine/api.rs index 3bdf56b..c912467 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -1,3 +1,5 @@ +//! Module contains the [EngineApi] client. + use std::collections::HashMap; use std::time::{Duration, SystemTime}; @@ -20,7 +22,7 @@ use super::{ use super::{JSONRPC_VERSION, STATIC_ID}; -/// An external op-geth engine api client +/// An external engine api client #[derive(Debug, Clone)] pub struct EngineApi { /// Base request url diff --git a/src/engine/auth.rs b/src/engine/auth.rs index fed17bd..e008eeb 100644 --- a/src/engine/auth.rs +++ b/src/engine/auth.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - //! Authentication module for the Engine API. //! //! This module was built using [reth](https://github.com/paradigmxyz/reth). diff --git a/src/engine/fork.rs b/src/engine/fork.rs index db5a628..5b80d10 100644 --- a/src/engine/fork.rs +++ b/src/engine/fork.rs @@ -1,3 +1,5 @@ +//! Forkchoice types. + use alloy_primitives::B256; use serde::{Deserialize, Serialize}; diff --git a/src/engine/mock_engine.rs b/src/engine/mock_engine.rs index c066885..6833491 100644 --- a/src/engine/mock_engine.rs +++ b/src/engine/mock_engine.rs @@ -1,3 +1,5 @@ +//! A mock L2 Engine API. + use async_trait::async_trait; use eyre::Result; diff --git a/src/engine/mod.rs b/src/engine/mod.rs index a60aa4b..24798d2 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -1,33 +1,29 @@ -#![warn(unreachable_pub)] -#![deny(missing_docs, missing_debug_implementations)] +//! L2 Engine API module. -/// Payload Types -mod payload; -pub use payload::*; +pub mod payload; +pub use payload::{ExecutionPayload, PayloadAttributes, PayloadId, PayloadStatus, Status}; -/// Forkchoice Types -mod fork; -pub use fork::*; +pub mod fork; +pub use fork::{ForkChoiceUpdate, ForkchoiceState}; -/// The Engine Drive -mod api; -pub use api::*; +pub mod api; +pub use api::{EngineApi, EngineApiErrorPayload, EngineApiResponse}; -/// Auth module -mod auth; -pub use auth::*; +pub mod auth; +pub use auth::JwtSecret; -/// Common Types -mod types; -pub use types::*; +pub mod params; +pub use params::{ + DEFAULT_AUTH_PORT, ENGINE_FORKCHOICE_UPDATED_TIMEOUT, ENGINE_FORKCHOICE_UPDATED_V2, + ENGINE_GET_PAYLOAD_TIMEOUT, ENGINE_GET_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_TIMEOUT, + ENGINE_NEW_PAYLOAD_V2, JSONRPC_VERSION, STATIC_ID, +}; -/// Core Trait -mod traits; -pub use traits::*; +pub mod traits; +pub use traits::Engine; -/// Mock Engine -mod mock_engine; -pub use mock_engine::*; +pub mod mock_engine; +pub use mock_engine::MockEngine; #[cfg(test)] mod tests { diff --git a/src/engine/types.rs b/src/engine/params.rs similarity index 97% rename from src/engine/types.rs rename to src/engine/params.rs index 9bae9bf..d674773 100644 --- a/src/engine/types.rs +++ b/src/engine/params.rs @@ -1,3 +1,5 @@ +//! Engine Parameters. + use std::time::Duration; /// The default engine api authentication port. diff --git a/src/engine/payload.rs b/src/engine/payload.rs index f14f74d..ca2e54a 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -1,3 +1,5 @@ +//! Payload types for the L2 execution engine. + use alloy_consensus::TxEnvelope; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{Address, Bytes, B256, U64}; diff --git a/src/engine/traits.rs b/src/engine/traits.rs index 3adc552..dc2a317 100644 --- a/src/engine/traits.rs +++ b/src/engine/traits.rs @@ -1,3 +1,5 @@ +//! Core [Engine] trait for the Engine API. + use async_trait::async_trait; use eyre::Result; diff --git a/src/l1/blob_encoding.rs b/src/l1/blob_encoding.rs index 8901d9f..6ca2c32 100644 --- a/src/l1/blob_encoding.rs +++ b/src/l1/blob_encoding.rs @@ -1,3 +1,5 @@ +//! Blob decoding module. + use alloy_primitives::Bytes; use eyre::Result; diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index b395501..8b93e73 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -1,3 +1,5 @@ +//! Blob fetching and extraction module. + use std::sync::atomic::{AtomicU64, Ordering}; use eyre::Result; diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index 90a7b36..f31ba80 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -1,3 +1,5 @@ +//! Contains the [ChainWatcher] which monitors L1 for new blocks and events. + use std::{collections::HashMap, sync::Arc, time::Duration}; use eyre::Result; @@ -15,17 +17,17 @@ use crate::{ l1::decode_blob_data, }; -use super::{l1_info::L1BlockInfo, BlobFetcher, L1Info, SystemConfigUpdate}; +use super::{BlobFetcher, L1BlockInfo, L1Info, SystemConfigUpdate}; -static CONFIG_UPDATE_TOPIC: Lazy = +pub static CONFIG_UPDATE_TOPIC: Lazy = Lazy::new(|| keccak256("ConfigUpdate(uint256,uint8,bytes)")); -static TRANSACTION_DEPOSITED_TOPIC: Lazy = +pub static TRANSACTION_DEPOSITED_TOPIC: Lazy = Lazy::new(|| keccak256("TransactionDeposited(address,address,uint256,bytes)")); /// The transaction type used to identify transactions that carry blobs /// according to EIP 4844. -const BLOB_CARRYING_TRANSACTION_TYPE: u64 = 3; +pub const BLOB_CARRYING_TRANSACTION_TYPE: u64 = 3; /// The data contained in a batcher transaction. /// The actual source of this data can be either calldata or blobs. diff --git a/src/l1/config_updates.rs b/src/l1/config_updates.rs index 6b05a1a..c9e1257 100644 --- a/src/l1/config_updates.rs +++ b/src/l1/config_updates.rs @@ -1,3 +1,5 @@ +//! Parses logs and extracts system config updates. + use alloy_primitives::{Address, U256, U64}; use alloy_rpc_types::Log; use eyre::Result; diff --git a/src/l1/l1_info.rs b/src/l1/l1_info.rs index 794415e..cf82eff 100644 --- a/src/l1/l1_info.rs +++ b/src/l1/l1_info.rs @@ -1,3 +1,5 @@ +//! Contains the L1 info types. + use alloy_primitives::{B256, U256}; use alloy_rpc_types::Block; diff --git a/src/l1/mod.rs b/src/l1/mod.rs index c09eb70..ca48e9f 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -1,21 +1,16 @@ -/// Module reposnsible for listening to the L1 chain and monitoring for new -/// blocks and events. +//! L1 Module is responsible for ingesting and processing L1 chain data. + pub mod chain_watcher; pub use chain_watcher::{BlockUpdate, ChainWatcher}; -/// module responsible for parsing logs to extract system config updates pub mod config_updates; pub use config_updates::SystemConfigUpdate; -/// L1 block info pub mod l1_info; -pub use l1_info::L1Info; +pub use l1_info::{L1BlockInfo, L1Info}; -/// Module responsible for extracting batcher transaction data from -/// L1 batcher transaction data or blobs (after the Ecotone hardfork) pub mod blob_fetcher; pub use blob_fetcher::{BlobFetcher, BlobSidecar}; -/// Helper module for decoding blob data pub mod blob_encoding; pub use blob_encoding::decode_blob_data; diff --git a/src/lib.rs b/src/lib.rs index c57938b..84919a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,36 +39,24 @@ //! //! Then, refer to the individual modules for specific functionality. //! -#![warn(missing_docs)] -/// A module for ingesting L1 chain data -pub mod l1; +#![doc = include_str!("../README.md")] +#![warn( + missing_debug_implementations, + missing_docs, + unreachable_pub, + rustdoc::all +)] +#![deny(unused_must_use, rust_2018_idioms)] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -/// Common types and functions pub mod common; - -/// Configuration management pub mod config; - -/// The derivation pipeline module for deriving the canonical L2 chain pub mod derive; - -/// A module for driving op-geth via the L2 Engine API pub mod driver; - -/// A module for the L2 Engine API pub mod engine; - -/// Peer to peer networking +pub mod l1; pub mod network; - -/// Application telemetry and logging -pub mod telemetry; - -/// RPC module to host rpc server pub mod rpc; - -/// A module to handle running Magi in different sync modes pub mod runner; - -/// A module to get current Magi version. +pub mod telemetry; pub mod version; diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index b84f451..9c2ffb9 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -1,3 +1,5 @@ +//! A module for handling blocks received via p2p gossip. + use std::sync::mpsc::{channel, Receiver, Sender}; use std::time::SystemTime; diff --git a/src/network/handlers/mod.rs b/src/network/handlers/mod.rs index 365f398..84fb9af 100644 --- a/src/network/handlers/mod.rs +++ b/src/network/handlers/mod.rs @@ -1,7 +1,9 @@ +//! Module contains the network handlers for processing incoming p2p gossip messages. + use libp2p::gossipsub::{Message, MessageAcceptance, TopicHash}; -/// A module for managing incoming p2p gossip messages pub mod block_handler; +pub use block_handler::BlockHandler; /// This trait defines the functionality required to process incoming messages /// and determine their acceptance within the network. Implementors of this trait diff --git a/src/network/mod.rs b/src/network/mod.rs index 8db0738..1db355b 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -1,4 +1,9 @@ -/// A module for managing incoming p2p gossip messages +//! Network Module +//! +//! Contains [handlers] and [service] peer to peer networking components. + pub mod handlers; -/// A module for managing the Discv5 discovery & libp2p services +pub use handlers::{BlockHandler, Handler}; + pub mod service; +pub use service::Service; diff --git a/src/network/service/mod.rs b/src/network/service/mod.rs index 6c4b6b3..65b8be6 100644 --- a/src/network/service/mod.rs +++ b/src/network/service/mod.rs @@ -1,3 +1,5 @@ +//! Module contains the Discv5 discovery & libp2p services. + use std::{net::SocketAddr, time::Duration}; use eyre::Result; diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index b758e10..6eadf89 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -1,3 +1,5 @@ +//! RPC module to host the RPC server. + use std::{fmt::Display, net::SocketAddr, sync::Arc}; use crate::{ diff --git a/src/runner/mod.rs b/src/runner/mod.rs index 5539123..cda8395 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -1,3 +1,5 @@ +//! Module handles running the Magi node. + use std::{process, str::FromStr, time::Duration}; use alloy_primitives::B256; diff --git a/src/telemetry/logging.rs b/src/telemetry/logging.rs index a0fa5ed..a479896 100644 --- a/src/telemetry/logging.rs +++ b/src/telemetry/logging.rs @@ -1,3 +1,5 @@ +//! Logging Module. + use std::{ env::current_dir, path::{Path, PathBuf}, @@ -14,10 +16,10 @@ use ansi_term::Colour::{Blue, Cyan, Purple, Red, Yellow}; /// Standard log file name prefix. This will be optionally appended with a timestamp /// depending on the rotation strategy. -const LOG_FILE_NAME_PREFIX: &str = "magi.log"; +pub const LOG_FILE_NAME_PREFIX: &str = "magi.log"; /// Default log file rotation strategy. This can be overridden by the `logs_rotation` config. -const DEFAULT_ROTATION: &str = "daily"; +pub const DEFAULT_ROTATION: &str = "daily"; /// Configure logging telemetry with a global handler. pub fn init( @@ -217,7 +219,7 @@ where /// Get the rotation strategy from the given string. /// Defaults to rotating daily. -fn get_rotation_strategy(val: &str) -> Rotation { +pub fn get_rotation_strategy(val: &str) -> Rotation { match val { "never" => Rotation::NEVER, "daily" => Rotation::DAILY, @@ -232,7 +234,7 @@ fn get_rotation_strategy(val: &str) -> Rotation { } /// Get a rolling file appender for the given directory, rotation and file name prefix. -fn get_rolling_file_appender( +pub fn get_rolling_file_appender( directory: PathBuf, rotation: Rotation, file_name_prefix: &str, diff --git a/src/telemetry/metrics.rs b/src/telemetry/metrics.rs index 5e29e32..d5019cc 100644 --- a/src/telemetry/metrics.rs +++ b/src/telemetry/metrics.rs @@ -1,3 +1,5 @@ +//! Prometheus Metrics Module. + use eyre::{Result, WrapErr}; use lazy_static::lazy_static; use prometheus_exporter::{ diff --git a/src/telemetry/mod.rs b/src/telemetry/mod.rs index d6482fc..22f1259 100644 --- a/src/telemetry/mod.rs +++ b/src/telemetry/mod.rs @@ -1,8 +1,6 @@ -#![deny(missing_debug_implementations)] - //! Telemetry module //! -//! This module encompasses telemetry for `magi`. +//! This module encompasses telemetry and logging. //! Core components are described below. //! //! ### Logging @@ -13,17 +11,21 @@ //! to initialize a global logger, passing in a boolean `verbose` parameter. This function //! will return an error if a logger has already been initialized. //! +//! ### Metrics +//! +//! Metrics are collected using the [prometheus](https://crates.io/crates/prometheus) crate. -/// The Logging Module pub mod logging; +pub use logging::{ + build_subscriber, get_rolling_file_appender, get_rotation_strategy, init, AnsiTermLayer, + AnsiVisitor, DEFAULT_ROTATION, LOG_FILE_NAME_PREFIX, +}; -/// Prometheus metrics pub mod metrics; +pub use metrics::{init as init_metrics, FINALIZED_HEAD, SAFE_HEAD, SYNCED}; -// Re-export inner modules -pub use logging::*; - -/// Export a prelude to re-export common traits and types +/// Contains common telemetry and logging types. +/// Re-exports [tracing] and [tracing_subscriber] items. pub mod prelude { pub use super::*; pub use tracing::{debug, error, info, span, trace, warn, Level}; diff --git a/src/version/mod.rs b/src/version/mod.rs index 93b785a..cd2f27d 100644 --- a/src/version/mod.rs +++ b/src/version/mod.rs @@ -1,4 +1,6 @@ -/// Represents the Magi version +//! Module containing the parsed crate [Version]. + +/// Represents the version #[derive(Debug)] pub struct Version { /// The package name specified in `Cargo.toml` From 4c371700efe65aa86c6e4bd98c202c32cf0decba Mon Sep 17 00:00:00 2001 From: refcell Date: Tue, 28 May 2024 14:32:56 -0400 Subject: [PATCH 5/5] fix: eyre to anyhow --- Cargo.lock | 159 ++++---- Cargo.toml | 11 +- bin/magi.rs | 2 +- bin/network.rs | 2 +- src/common/attributes_deposited.rs | 21 +- src/common/mod.rs | 16 +- src/config/mod.rs | 11 +- src/derive/ecotone_upgrade.rs | 418 ++++++++++++++++------ src/derive/mod.rs | 2 +- src/derive/pipeline.rs | 2 +- src/derive/stages/attributes.rs | 26 +- src/derive/stages/batcher_transactions.rs | 10 +- src/derive/stages/batches.rs | 6 +- src/derive/stages/block_input.rs | 6 +- src/derive/stages/span_batch.rs | 8 +- src/derive/state.rs | 1 + src/driver/engine_driver.rs | 10 +- src/driver/info.rs | 2 +- src/driver/node_driver.rs | 18 +- src/driver/types.rs | 22 +- src/engine/api.rs | 16 +- src/engine/auth.rs | 4 +- src/engine/mock_engine.rs | 2 +- src/engine/payload.rs | 18 +- src/engine/traits.rs | 2 +- src/l1/blob_encoding.rs | 12 +- src/l1/blob_fetcher.rs | 20 +- src/l1/chain_watcher.rs | 32 +- src/l1/config_updates.rs | 22 +- src/l1/l1_info.rs | 10 +- src/network/handlers/block_handler.rs | 2 +- src/network/service/discovery.rs | 4 +- src/network/service/enr.rs | 4 +- src/network/service/mod.rs | 10 +- src/network/service/types.rs | 14 +- src/rpc/mod.rs | 2 +- src/runner/mod.rs | 14 +- src/telemetry/metrics.rs | 8 +- 38 files changed, 565 insertions(+), 384 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0548e0..9de6902 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,12 +146,23 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-consensus" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=cb95183#cb95183d477024b57b27336035d10403e8ba55b8" dependencies = [ - "alloy-eips", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "sha2 0.10.8", +] + +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" +dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "c-kzg", "serde", "sha2 0.10.8", @@ -160,11 +171,21 @@ dependencies = [ [[package]] name = "alloy-eips" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=cb95183#cb95183d477024b57b27336035d10403e8ba55b8" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "c-kzg", "once_cell", "serde", @@ -173,38 +194,35 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", - "alloy-serde", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "serde", - "serde_json", ] [[package]] name = "alloy-json-rpc" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", "serde", "serde_json", "thiserror", - "tracing", ] [[package]] name = "alloy-network" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-json-rpc", "alloy-primitives", "alloy-rpc-types", "alloy-signer", - "alloy-sol-types", "async-trait", "futures-utils-wasm", "thiserror", @@ -235,9 +253,8 @@ dependencies = [ [[package]] name = "alloy-provider" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-primitives", @@ -251,7 +268,6 @@ dependencies = [ "auto_impl", "dashmap", "futures", - "futures-utils-wasm", "lru 0.12.3", "reqwest 0.12.4", "serde_json", @@ -285,7 +301,7 @@ dependencies = [ [[package]] name = "alloy-rpc-client" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -305,14 +321,14 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-genesis", "alloy-primitives", "alloy-rlp", - "alloy-serde", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-sol-types", "itertools 0.12.1", "serde", @@ -323,11 +339,21 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", "alloy-rpc-types", - "alloy-serde", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=cb95183#cb95183d477024b57b27336035d10403e8ba55b8" +dependencies = [ + "alloy-primitives", "serde", "serde_json", ] @@ -335,7 +361,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", "serde", @@ -345,7 +371,7 @@ dependencies = [ [[package]] name = "alloy-signer" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", "async-trait", @@ -402,7 +428,7 @@ dependencies = [ [[package]] name = "alloy-transport" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-json-rpc", "base64 0.22.0", @@ -420,7 +446,7 @@ dependencies = [ [[package]] name = "alloy-transport-http" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#0ac4e49ba5899d4a9db7cc876d9f54f5a24232d4" +source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -1707,16 +1733,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - [[package]] name = "fastrand" version = "2.0.1" @@ -2401,22 +2417,6 @@ dependencies = [ "tokio-native-tls", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.3.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.3" @@ -2530,12 +2530,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - [[package]] name = "indexmap" version = "1.9.3" @@ -3258,13 +3252,13 @@ name = "magi" version = "0.1.0" dependencies = [ "again", - "alloy-consensus", - "alloy-eips", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-primitives", "alloy-provider", "alloy-rlp", "alloy-rpc-types", "ansi_term", + "anyhow", "async-trait", "bytes", "chrono", @@ -3272,7 +3266,6 @@ dependencies = [ "ctrlc", "dirs", "discv5", - "eyre", "figment", "futures", "futures-timer 0.3.0", @@ -3284,6 +3277,7 @@ dependencies = [ "libp2p", "libp2p-identity", "once_cell", + "op-alloy-consensus", "openssl", "prometheus_exporter", "rand 0.8.5", @@ -3291,6 +3285,7 @@ dependencies = [ "serde", "serde_json", "snap", + "spin 0.9.8", "ssz_rs", "tokio", "tracing", @@ -3636,6 +3631,17 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "op-alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/clabby/op-alloy?branch=refcell/consensus-port#74ed6337b600a7f77fa10568be0f054042f70400" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", + "alloy-primitives", + "alloy-rlp", +] + [[package]] name = "opaque-debug" version = "0.3.0" @@ -4356,7 +4362,7 @@ dependencies = [ "http 0.2.11", "http-body 0.4.6", "hyper 0.14.28", - "hyper-tls 0.5.0", + "hyper-tls", "ipnet", "js-sys", "log", @@ -4365,7 +4371,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -4395,23 +4401,19 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls 0.6.0", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.2", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", "tower-service", "url", "wasm-bindgen", @@ -4620,22 +4622,6 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-pemfile" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" -dependencies = [ - "base64 0.22.0", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" - [[package]] name = "rusty-fork" version = "0.3.0" @@ -5009,6 +4995,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" diff --git a/Cargo.toml b/Cargo.toml index b4e2f85..cb2a80a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ path = "./bin/network.rs" [dependencies] tokio = { version = "1.28.0", features = ["full"] } async-trait = "0.1.73" -eyre = "0.6.8" +anyhow = "1.0" hex = "0.4.3" libflate = "1.2.0" openssl = { version = "0.10", features = ["vendored"] } @@ -25,14 +25,15 @@ jsonrpsee = {version = "0.17.0", features = ["server", "macros"]} futures = "0.3.28" futures-timer = "0.3.0" again = "0.1" +spin = { version = "0.9.8", features = ["mutex"] } # Alloy types alloy-rlp = { version = "0.3", default-features = false } alloy-primitives = { version = "0.7.1", default-features = false, features = ["serde"] } -alloy-provider = { git = "https://github.com/alloy-rs/alloy", features = [ "reqwest" ] } -alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy" } -alloy-consensus = { git = "https://github.com/alloy-rs/alloy" } -alloy-eips = { git = "https://github.com/alloy-rs/alloy" } +alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "e3f2f07", features = [ "reqwest" ] } +alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "e3f2f07" } +op-alloy-consensus = { git = "https://github.com/clabby/op-alloy", branch = "refcell/consensus-port", default-features = false } +alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "e3f2f07", default-features = false } # Logging and Metrics chrono = "0.4.22" diff --git a/bin/magi.rs b/bin/magi.rs index a162025..c527422 100644 --- a/bin/magi.rs +++ b/bin/magi.rs @@ -3,7 +3,7 @@ use std::{env::current_dir, process}; use clap::Parser; use dirs::home_dir; -use eyre::Result; +use anyhow::Result; use magi::{ config::{ChainConfig, CliConfig, Config, SyncMode}, diff --git a/bin/network.rs b/bin/network.rs index eba1c28..cf533c8 100644 --- a/bin/network.rs +++ b/bin/network.rs @@ -1,5 +1,5 @@ use alloy_primitives::address; -use eyre::Result; +use anyhow::Result; use magi::{ network::{handlers::block_handler::BlockHandler, service::Service}, diff --git a/src/common/attributes_deposited.rs b/src/common/attributes_deposited.rs index c07d87f..59c7d4f 100644 --- a/src/common/attributes_deposited.rs +++ b/src/common/attributes_deposited.rs @@ -1,4 +1,4 @@ -use eyre::Result; +use anyhow::Result; use lazy_static::lazy_static; use alloy_primitives::{keccak256, Bytes, B256, U256}; @@ -67,12 +67,12 @@ impl AttributesDepositedCall { let mut cursor = 0; if calldata.len() != L1_INFO_BEDROCK_LEN { - eyre::bail!("invalid calldata length"); + anyhow::bail!("invalid calldata length"); } let selector = &calldata[cursor..cursor + 4]; if selector != *SET_L1_BLOCK_VALUES_BEDROCK_SELECTOR { - eyre::bail!("invalid selector"); + anyhow::bail!("invalid selector"); } cursor += 4; @@ -80,14 +80,14 @@ impl AttributesDepositedCall { // down-casting to u64 is safe for the block number let number = number .try_into() - .map_err(|_| eyre::eyre!("invalid block number"))?; + .map_err(|_| anyhow::anyhow!("invalid block number"))?; cursor += 32; let timestamp = U256::from_be_slice(calldata[cursor..cursor + 32].try_into()?); // down-casting to u64 is safe for UNIX timestamp let timestamp = timestamp .try_into() - .map_err(|_| eyre::eyre!("invalid timestamp"))?; + .map_err(|_| anyhow::anyhow!("invalid timestamp"))?; cursor += 32; let basefee = U256::from_be_slice(&calldata[cursor..cursor + 32]); @@ -100,7 +100,7 @@ impl AttributesDepositedCall { // down-casting to u64 is safe for the sequence number let sequence_number = sequence_number .try_into() - .map_err(|_| eyre::eyre!("invalid sequence number"))?; + .map_err(|_| anyhow::anyhow!("invalid sequence number"))?; cursor += 32; let batcher_hash = B256::from_slice(&calldata[cursor..cursor + 32]); @@ -148,12 +148,12 @@ impl AttributesDepositedCall { let mut cursor = 0; if calldata.len() != L1_INFO_ECOTONE_LEN { - eyre::bail!("invalid calldata length"); + anyhow::bail!("invalid calldata length"); } let selector = &calldata[cursor..cursor + 4]; if selector != *SET_L1_BLOCK_VALUES_ECOTONE_SELECTOR { - eyre::bail!("invalid selector"); + anyhow::bail!("invalid selector"); } cursor += 4; @@ -206,13 +206,14 @@ impl AttributesDepositedCall { mod tests { mod attributed_deposited_call { use std::str::FromStr; + use anyhow::Result; use alloy_primitives::{Bytes, B256, U256}; use crate::common::AttributesDepositedCall; #[test] - fn decode_from_bytes_bedrock() -> eyre::Result<()> { + fn decode_from_bytes_bedrock() -> Result<()> { // Arrange let calldata = "0x015d8eb900000000000000000000000000000000000000000000000000000000008768240000000000000000000000000000000000000000000000000000000064443450000000000000000000000000000000000000000000000000000000000000000e0444c991c5fe1d7291ff34b3f5c3b44ee861f021396d33ba3255b83df30e357d00000000000000000000000000000000000000000000000000000000000000050000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"; @@ -236,7 +237,7 @@ mod tests { } #[test] - fn decode_from_bytes_ecotone() -> eyre::Result<()> { + fn decode_from_bytes_ecotone() -> Result<()> { // Arrange // https://goerli-optimism.etherscan.io/tx/0xc2288c5d1f6123406bfe8662bdbc1a3c999394da2e6f444f5aa8df78136f36ba let calldata = "0x440a5e2000001db0000d273000000000000000050000000065c8ad6c0000000000a085a20000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000041dfd80f2c8af7d7ba1c1a3962026e5c96b9105d528f8fed65c56cfa731a8751c7f712eb70000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9"; diff --git a/src/common/mod.rs b/src/common/mod.rs index 4285d2a..c6bb2c4 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -2,9 +2,9 @@ use std::fmt::Debug; -use alloy_primitives::B256; +use alloy_primitives::{Bytes, B256}; use alloy_rpc_types::Block; -use eyre::Result; +use anyhow::Result; use figment::value::{Dict, Tag, Value}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; @@ -31,6 +31,12 @@ pub struct BlockInfo { #[derive(Clone, alloy_rlp::RlpDecodable, alloy_rlp::RlpEncodable, PartialEq, Eq)] pub struct RawTransaction(pub Vec); +impl> From for RawTransaction { + fn from(bytes: T) -> Self { + Self(bytes.into().to_vec()) + } +} + /// L1 epoch block #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] pub struct Epoch { @@ -57,17 +63,17 @@ impl From for Value { } impl TryFrom for BlockInfo { - type Error = eyre::Report; + type Error = anyhow::Error; /// Converts a [Block] to [BlockInfo] fn try_from(block: Block) -> Result { let number = block .header .number - .ok_or(eyre::eyre!("block not included"))? + .ok_or(anyhow::anyhow!("block not included"))? .try_into()?; - let hash = block.header.hash.ok_or(eyre::eyre!("block not included"))?; + let hash = block.header.hash.ok_or(anyhow::anyhow!("block not included"))?; let timestamp = block.header.timestamp.try_into()?; Ok(BlockInfo { diff --git a/src/config/mod.rs b/src/config/mod.rs index ecd54cb..945b844 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -294,16 +294,17 @@ impl ChainConfig { } /// Returns true if the block is the first block subject to the Ecotone hardfork - pub fn is_ecotone_activation_block(&self, l2_block_timestamp: impl Into) -> bool { - l2_block_timestamp.into() == U64::from(self.ecotone_time) + pub fn is_ecotone_activation_block(&self, l2_block_timestamp: &U64) -> bool { + *l2_block_timestamp == U64::from(self.ecotone_time) } /// Returns true if Ecotone hardfork is active but the block is not the /// first block subject to the hardfork. Ecotone activation at genesis does not count. pub fn is_ecotone_but_not_first_block(&self, l2_block_timestamp: impl Into) -> bool { - let is_ecotone = l2_block_timestamp.into() >= U64::from(self.ecotone_time); - - is_ecotone && !self.is_ecotone_activation_block(l2_block_timestamp) + let l2_block_timestamp = l2_block_timestamp.into(); + let is_activation_block = self.is_ecotone_activation_block(&l2_block_timestamp); + let is_ecotone = l2_block_timestamp >= U64::from(self.ecotone_time); + is_ecotone && !is_activation_block } /// [ChainConfig] for Optimism diff --git a/src/derive/ecotone_upgrade.rs b/src/derive/ecotone_upgrade.rs index 831952e..1cadc82 100644 --- a/src/derive/ecotone_upgrade.rs +++ b/src/derive/ecotone_upgrade.rs @@ -1,124 +1,304 @@ -//! A module that handles the Ecotone Hardfork Upgrade. +//! Module containing a [Transaction] builder for the Ecotone network updgrade transactions. +//! +//! [Transaction]: alloy_consensus::Transaction -use std::str::FromStr; +use crate::common::RawTransaction; +use std::string::String; +use std::vec::Vec; +use alloy_primitives::{address, keccak256, B256, bytes, Address, Bytes, TxKind, U256}; +use alloy_rlp::Encodable; +use op_alloy_consensus::{OpTxEnvelope, TxDeposit}; +use spin::Lazy; -use alloy_consensus::TxEnvelope; -use alloy_primitives::{address, b256, uint, Address, Bytes, U256, U64}; +/// Source domain identifiers for deposit transactions. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[repr(u8)] +pub enum DepositSourceDomainIdentifier { + /// A user deposit source. + User = 0, + /// A L1 info deposit source. + L1Info = 1, + /// An upgrade deposit source. + Upgrade = 2, +} -use crate::common::RawTransaction; +/// Source domains for deposit transactions. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum DepositSourceDomain { + /// A user deposit source. + User(UserDepositSource), + /// A L1 info deposit source. + L1Info(L1InfoDepositSource), + /// An upgrade deposit source. + Upgrade(UpgradeDepositSource), +} + +impl DepositSourceDomain { + /// Returns the source hash. + pub fn source_hash(&self) -> B256 { + match self { + Self::User(ds) => ds.source_hash(), + Self::L1Info(ds) => ds.source_hash(), + Self::Upgrade(ds) => ds.source_hash(), + } + } +} + + +/// A deposit transaction source. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UserDepositSource { + /// The L1 block hash. + pub l1_block_hash: B256, + /// The log index. + pub log_index: u64, +} + +impl UserDepositSource { + /// Creates a new [UserDepositSource]. + pub fn new(l1_block_hash: B256, log_index: u64) -> Self { + Self { l1_block_hash, log_index } + } + + /// Returns the source hash. + pub fn source_hash(&self) -> B256 { + let mut input = [0u8; 32 * 2]; + input[..32].copy_from_slice(&self.l1_block_hash[..]); + input[32 * 2 - 8..].copy_from_slice(&self.log_index.to_be_bytes()); + let deposit_id_hash = keccak256(input); + let mut domain_input = [0u8; 32 * 2]; + let identifier_bytes: [u8; 8] = (DepositSourceDomainIdentifier::User as u64).to_be_bytes(); + domain_input[32 - 8..32].copy_from_slice(&identifier_bytes); + domain_input[32..].copy_from_slice(&deposit_id_hash[..]); + keccak256(domain_input) + } +} + +/// A L1 info deposit transaction source. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct L1InfoDepositSource { + /// The L1 block hash. + pub l1_block_hash: B256, + /// The sequence number. + pub seq_number: u64, +} + +impl L1InfoDepositSource { + /// Creates a new [L1InfoDepositSource]. + pub fn new(l1_block_hash: B256, seq_number: u64) -> Self { + Self { l1_block_hash, seq_number } + } + + /// Returns the source hash. + pub fn source_hash(&self) -> B256 { + let mut input = [0u8; 32 * 2]; + input[..32].copy_from_slice(&self.l1_block_hash[..]); + input[32 * 2 - 8..].copy_from_slice(&self.seq_number.to_be_bytes()); + let deposit_id_hash = keccak256(input); + let mut domain_input = [0u8; 32 * 2]; + let identifier_bytes: [u8; 8] = + (DepositSourceDomainIdentifier::L1Info as u64).to_be_bytes(); + domain_input[32 - 8..32].copy_from_slice(&identifier_bytes); + domain_input[32..].copy_from_slice(&deposit_id_hash[..]); + keccak256(domain_input) + } +} + +/// An upgrade deposit transaction source. +/// This implements the translation of upgrade-tx identity information to a deposit source-hash, +/// which makes the deposit uniquely identifiable. +/// System-upgrade transactions have their own domain for source-hashes, +/// to not conflict with user-deposits or deposited L1 information. +/// The intent identifies the upgrade-tx uniquely, in a human-readable way. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UpgradeDepositSource { + /// The intent. + pub intent: String, +} + +impl UpgradeDepositSource { + /// Creates a new [UpgradeDepositSource]. + pub fn new(intent: String) -> Self { + Self { intent } + } + + /// Returns the source hash. + pub fn source_hash(&self) -> B256 { + let intent_hash = keccak256(self.intent.as_bytes()); + let mut domain_input = [0u8; 32 * 2]; + let identifier_bytes: [u8; 8] = + (DepositSourceDomainIdentifier::Upgrade as u64).to_be_bytes(); + domain_input[32 - 8..32].copy_from_slice(&identifier_bytes); + domain_input[32..].copy_from_slice(&intent_hash[..]); + keccak256(domain_input) + } +} + +/// The UpdgradeTo Function Signature +pub const UPDGRADE_TO_FUNC_SIGNATURE: &str = "upgradeTo(address)"; + +/// L1 Block Deployer Address +pub const L1_BLOCK_DEPLOYER_ADDRESS: Address = address!("4210000000000000000000000000000000000000"); + +/// The Gas Price Oracle Deployer Address +pub const GAS_PRICE_ORACLE_DEPLOYER_ADDRESS: Address = + address!("4210000000000000000000000000000000000001"); -/// Return the generated Ecotone upgrade RLP-encoded transactions -/// as defined in the [specs]. -/// -/// [specs]: https://specs.optimism.io/protocol/derivation.html#ecotone -pub fn get_ecotone_upgrade_transactions() -> Vec { - let mut upgrade_transactions = Vec::with_capacity(6); - - // Deploy the L1 Block Contract - let mut buffer = Vec::new(); - TxEnvelope::Deposit(TxDeposit { - source_hash: DEPLOY_L1_BLOCK_SOURCE.source_hash(), - from: L1_BLOCK_DEPLOYER_ADDRESS, - to: TxKind::Create, - mint: 0.into(), - value: U256::ZERO, - gas_limit: 375_000, - is_system_transaction: false, - input: l1_block_deployment_bytecode, - }) - .encode(&mut buffer); - upgrade_transactions.push(RawTransaction::from(buffer)); - - let deploy_l1_block = Transaction { - transaction_type: Some(U64::from(0x7E)), - source_hash: b256!("877a6077205782ea15a6dc8699fa5ebcec5e0f4389f09cb8eda09488231346f8"), - from: address!("4210000000000000000000000000000000000000"), - to: None, - mint: None, - value: U256::ZERO(), - gas: uint!(375_000_U256), - is_system_tx: false, - input: Bytes::from_str("0x608060405234801561001057600080fd5b5061053e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638381f58a11610097578063c598591811610066578063c598591814610229578063e591b28214610249578063e81b2c6d14610289578063f82061401461029257600080fd5b80638381f58a146101e35780638b239f73146101f75780639e8c496614610200578063b80777ea1461020957600080fd5b806354fd4d50116100d357806354fd4d50146101335780635cf249691461017c57806364ca23ef1461018557806368d5dca6146101b257600080fd5b8063015d8eb9146100fa57806309bd5a601461010f578063440a5e201461012b575b600080fd5b61010d61010836600461044c565b61029b565b005b61011860025481565b6040519081526020015b60405180910390f35b61010d6103da565b61016f6040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161012291906104be565b61011860015481565b6003546101999067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610122565b6003546101ce9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610122565b6000546101999067ffffffffffffffff1681565b61011860055481565b61011860065481565b6000546101999068010000000000000000900467ffffffffffffffff1681565b6003546101ce906c01000000000000000000000000900463ffffffff1681565b61026473deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b61011860045481565b61011860075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b3373deaddeaddeaddeaddeaddeaddeaddeaddead00011461040357633cc50b456000526004601cfd5b60043560801c60035560143560801c600055602435600155604435600755606435600255608435600455565b803567ffffffffffffffff8116811461044757600080fd5b919050565b600080600080600080600080610100898b03121561046957600080fd5b6104728961042f565b975061048060208a0161042f565b9650604089013595506060890135945061049c60808a0161042f565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b818110156104eb578581018301518582016040015282016104cf565b818111156104fd576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201604001939250505056fea164736f6c634300080f000a").unwrap(), - ..Default::default() - }; - upgrade_transactions.push(RawTransaction(deploy_l1_block.rlp().to_vec())); - - let deploy_gas_price_oracle = Transaction { - transaction_type: Some(U64::from(0x7E)), - source_hash: b256!("a312b4510adf943510f05fcc8f15f86995a5066bd83ce11384688ae20e6ecf42"), - from: address!("4210000000000000000000000000000000000001"), - to: None, - mint: None, - value: U256::ZERO(), - gas: uint!(1_000_000_U256), - is_system_tx: false, - input: Bytes::from_str("0x608060405234801561001057600080fd5b50610fb5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806354fd4d5011610097578063de26c4a111610066578063de26c4a1146101da578063f45e65d8146101ed578063f8206140146101f5578063fe173b97146101cc57600080fd5b806354fd4d501461016657806368d5dca6146101af5780636ef25c3a146101cc578063c5985918146101d257600080fd5b8063313ce567116100d3578063313ce5671461012757806349948e0e1461012e5780634ef6e22414610141578063519b4bd31461015e57600080fd5b80630c18c162146100fa57806322b90ab3146101155780632e0f26251461011f575b600080fd5b6101026101fd565b6040519081526020015b60405180910390f35b61011d61031e565b005b610102600681565b6006610102565b61010261013c366004610b73565b610541565b60005461014e9060ff1681565b604051901515815260200161010c565b610102610565565b6101a26040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161010c9190610c42565b6101b76105c6565b60405163ffffffff909116815260200161010c565b48610102565b6101b761064b565b6101026101e8366004610b73565b6106ac565b610102610760565b610102610853565b6000805460ff1615610296576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f47617350726963654f7261636c653a206f76657268656164282920697320646560448201527f707265636174656400000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610cb5565b905090565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663e591b2826040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a19190610cce565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e2073657420697345636f746f6e6520666c6160648201527f6700000000000000000000000000000000000000000000000000000000000000608482015260a40161028d565b60005460ff1615610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a2045636f746f6e6520616c72656164792060448201527f6163746976650000000000000000000000000000000000000000000000000000606482015260840161028d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000805460ff161561055c57610556826108b4565b92915050565b61055682610958565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff166368d5dca66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610d04565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663c59859186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b6000806106b883610ab4565b60005490915060ff16156106cc5792915050565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561072b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074f9190610cb5565b6107599082610d59565b9392505050565b6000805460ff16156107f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a207363616c61722829206973206465707260448201527f6563617465640000000000000000000000000000000000000000000000000000606482015260840161028d565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663f82061406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b6000806108c083610ab4565b905060006108cc610565565b6108d461064b565b6108df906010610d71565b63ffffffff166108ef9190610d9d565b905060006108fb610853565b6109036105c6565b63ffffffff166109139190610d9d565b905060006109218284610d59565b61092b9085610d9d565b90506109396006600a610efa565b610944906010610d9d565b61094e9082610f06565b9695505050505050565b60008061096483610ab4565b9050600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109eb9190610cb5565b6109f3610565565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a769190610cb5565b610a809085610d59565b610a8a9190610d9d565b610a949190610d9d565b9050610aa26006600a610efa565b610aac9082610f06565b949350505050565b80516000908190815b81811015610b3757848181518110610ad757610ad7610f41565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016600003610b1757610b10600484610d59565b9250610b25565b610b22601084610d59565b92505b80610b2f81610f70565b915050610abd565b50610aac82610440610d59565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610b8557600080fd5b813567ffffffffffffffff80821115610b9d57600080fd5b818401915084601f830112610bb157600080fd5b813581811115610bc357610bc3610b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610c0957610c09610b44565b81604052828152876020848701011115610c2257600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b81811015610c6f57858101830151858201604001528201610c53565b81811115610c81576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610cc757600080fd5b5051919050565b600060208284031215610ce057600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461075957600080fd5b600060208284031215610d1657600080fd5b815163ffffffff8116811461075957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610d6c57610d6c610d2a565b500190565b600063ffffffff80831681851681830481118215151615610d9457610d94610d2a565b02949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610dd557610dd5610d2a565b500290565b600181815b80851115610e3357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610e1957610e19610d2a565b80851615610e2657918102915b93841c9390800290610ddf565b509250929050565b600082610e4a57506001610556565b81610e5757506000610556565b8160018114610e6d5760028114610e7757610e93565b6001915050610556565b60ff841115610e8857610e88610d2a565b50506001821b610556565b5060208310610133831016604e8410600b8410161715610eb6575081810a610556565b610ec08383610dda565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610ef257610ef2610d2a565b029392505050565b60006107598383610e3b565b600082610f3c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610fa157610fa1610d2a565b506001019056fea164736f6c634300080f000a").unwrap(), - ..Default::default() - }; - upgrade_transactions.push(RawTransaction(deploy_gas_price_oracle.rlp().to_vec())); - - let update_l1_block_proxy = Transaction { - transaction_type: Some(U64::from(0x7E)), - source_hash: b256!("18acb38c5ff1c238a7460ebc1b421fa49ec4874bdf1e0a530d234104e5e67dbc") - .unwrap(), - from: address!("0000000000000000000000000000000000000000"), - to: Some(address!("4200000000000000000000000000000000000015")), - mint: None, - value: U256::ZERO(), - gas: uint!(50_000_U256), - is_system_tx: false, - input: Bytes::from_str( - "0x3659cfe600000000000000000000000007dbe8500fc591d1852b76fee44d5a05e13097ff", - ) - .unwrap(), - ..Default::default() - }; - upgrade_transactions.push(RawTransaction(update_l1_block_proxy.rlp().to_vec())); - - let update_gas_price_oracle_proxy = Transaction { - transaction_type: Some(U64::from(0x7E)), - source_hash: b256!("ee4f9385eceef498af0be7ec5862229f426dec41c8d42397c7257a5117d9230a"), - from: address!("0000000000000000000000000000000000000000"), - to: Some(Address::from_str("0x420000000000000000000000000000000000000F").unwrap()), - mint: None, - value: U256::ZERO(), - gas: uint!(50_000_U256), - is_system_tx: false, - input: Bytes::from_str( - "0x3659cfe6000000000000000000000000b528d11cc114e026f138fe568744c6d45ce6da7a", - ) - .unwrap(), - ..Default::default() - }; - upgrade_transactions.push(RawTransaction(update_gas_price_oracle_proxy.rlp().to_vec())); - - let enable_ecotone = Transaction { - transaction_type: Some(U64::from(0x7E)), - source_hash: b256!("0c1cb38e99dbc9cbfab3bb80863380b0905290b37eb3d6ab18dc01c1f3e75f93"), - from: address!("DeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001"), - to: Some(address!("420000000000000000000000000000000000000F")), - mint: None, - value: U256::ZERO(), - gas: uint!(80_000_U256), - is_system_tx: false, - input: Bytes::from_str("0x22b90ab3").unwrap(), - ..Default::default() - }; - upgrade_transactions.push(RawTransaction(enable_ecotone.rlp().to_vec())); - - let deploy_eip4788 = Transaction { - transaction_type: Some(U64::from(0x7E)), - source_hash: b256!("69b763c48478b9dc2f65ada09b3d92133ec592ea715ec65ad6e7f3dc519dc00c"), - from: address!("0B799C86a49DEeb90402691F1041aa3AF2d3C875"), - to: None, - mint: None, - value: U256::ZERO(), - gas: uint!(0x3d090_U256), - is_system_tx: false, - input: Bytes::from_str("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500").unwrap(), - ..Default::default() - }; - upgrade_transactions.push(RawTransaction(deploy_eip4788.rlp().to_vec())); - - upgrade_transactions +/// The new L1 Block Address +/// This is computed by using go-ethereum's `crypto.CreateAddress` function, +/// with the L1 Block Deployer Address and nonce 0. +pub const NEW_L1_BLOCK_ADDRESS: Address = address!("07dbe8500fc591d1852b76fee44d5a05e13097ff"); + +/// The Gas Price Oracle Address +/// This is computed by using go-ethereum's `crypto.CreateAddress` function, +/// with the Gas Price Oracle Deployer Address and nonce 0. +pub const GAS_PRICE_ORACLE_ADDRESS: Address = address!("b528d11cc114e026f138fe568744c6d45ce6da7a"); + +/// The Enable Ecotone Input Method 4Byte Signature +pub const ENABLE_ECOTONE_INPUT: &[u8] = &[0x22, 0xb9, 0x08, 0xb3]; + +/// UpgradeTo Function 4Byte Signature +pub const UPGRADE_TO_FUNC_BYTES_4: &[u8] = &[0x36, 0x59, 0xcf, 0xe6]; + +/// EIP-4788 From Address +pub const EIP4788_FROM: Address = address!("0B799C86a49DEeb90402691F1041aa3AF2d3C875"); + +static DEPLOY_L1_BLOCK_SOURCE: Lazy = + Lazy::new(|| UpgradeDepositSource { intent: String::from("Ecotone: L1 Block Deployment") }); + +static DEPLOY_GAS_PRICE_ORACLE_SOURCE: Lazy = Lazy::new(|| { + UpgradeDepositSource { intent: String::from("Ecotone: Gas Price Oracle Deployment") } +}); + +static UPDATE_L1_BLOCK_PROXY_SOURCE: Lazy = + Lazy::new(|| UpgradeDepositSource { intent: String::from("Ecotone: L1 Block Proxy Update") }); + +static UPDATE_GAS_PRICE_ORACLE_SOURCE: Lazy = Lazy::new(|| { + UpgradeDepositSource { intent: String::from("Ecotone: Gas Price Oracle Proxy Update") } +}); + +static ENABLE_ECOTONE_SOURCE: Lazy = Lazy::new(|| UpgradeDepositSource { + intent: String::from("Ecotone: Gas Price Oracle Set Ecotone"), +}); + +static BEACON_ROOTS_SOURCE: Lazy = Lazy::new(|| UpgradeDepositSource { + intent: String::from("Ecotone: beacon block roots contract deployment"), +}); + +/// Turns the given address into calldata for the `upgradeTo` function. +pub fn upgrade_to_calldata(addr: Address) -> Bytes { + let mut v = UPGRADE_TO_FUNC_BYTES_4.to_vec(); + v.extend_from_slice(addr.as_slice()); + Bytes::from(v) } + +/// Builder wrapper for the Ecotone network updgrade. +#[derive(Debug, Default)] +pub struct EcotoneTransactionBuilder; + +impl EcotoneTransactionBuilder { + /// Constructs the Ecotone network upgrade transactions. + pub fn build_txs() -> anyhow::Result> { + let mut txs = vec![]; + + let eip4788_creation_data = bytes!("60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500"); + + let l1_block_deployment_bytecode = bytes!("608060405234801561001057600080fd5b5061053e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638381f58a11610097578063c598591811610066578063c598591814610229578063e591b28214610249578063e81b2c6d14610289578063f82061401461029257600080fd5b80638381f58a146101e35780638b239f73146101f75780639e8c496614610200578063b80777ea1461020957600080fd5b806354fd4d50116100d357806354fd4d50146101335780635cf249691461017c57806364ca23ef1461018557806368d5dca6146101b257600080fd5b8063015d8eb9146100fa57806309bd5a601461010f578063440a5e201461012b575b600080fd5b61010d61010836600461044c565b61029b565b005b61011860025481565b6040519081526020015b60405180910390f35b61010d6103da565b61016f6040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161012291906104be565b61011860015481565b6003546101999067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610122565b6003546101ce9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610122565b6000546101999067ffffffffffffffff1681565b61011860055481565b61011860065481565b6000546101999068010000000000000000900467ffffffffffffffff1681565b6003546101ce906c01000000000000000000000000900463ffffffff1681565b61026473deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b61011860045481565b61011860075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b3373deaddeaddeaddeaddeaddeaddeaddeaddead00011461040357633cc50b456000526004601cfd5b60043560801c60035560143560801c600055602435600155604435600755606435600255608435600455565b803567ffffffffffffffff8116811461044757600080fd5b919050565b600080600080600080600080610100898b03121561046957600080fd5b6104728961042f565b975061048060208a0161042f565b9650604089013595506060890135945061049c60808a0161042f565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b818110156104eb578581018301518582016040015282016104cf565b818111156104fd576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201604001939250505056fea164736f6c634300080f000a"); + + let gas_price_oracle_deployment_bytecode = + bytes!("608060405234801561001057600080fd5b50610fb5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806354fd4d5011610097578063de26c4a111610066578063de26c4a1146101da578063f45e65d8146101ed578063f8206140146101f5578063fe173b97146101cc57600080fd5b806354fd4d501461016657806368d5dca6146101af5780636ef25c3a146101cc578063c5985918146101d257600080fd5b8063313ce567116100d3578063313ce5671461012757806349948e0e1461012e5780634ef6e22414610141578063519b4bd31461015e57600080fd5b80630c18c162146100fa57806322b90ab3146101155780632e0f26251461011f575b600080fd5b6101026101fd565b6040519081526020015b60405180910390f35b61011d61031e565b005b610102600681565b6006610102565b61010261013c366004610b73565b610541565b60005461014e9060ff1681565b604051901515815260200161010c565b610102610565565b6101a26040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161010c9190610c42565b6101b76105c6565b60405163ffffffff909116815260200161010c565b48610102565b6101b761064b565b6101026101e8366004610b73565b6106ac565b610102610760565b610102610853565b6000805460ff1615610296576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f47617350726963654f7261636c653a206f76657268656164282920697320646560448201527f707265636174656400000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610cb5565b905090565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663e591b2826040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a19190610cce565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e2073657420697345636f746f6e6520666c6160648201527f6700000000000000000000000000000000000000000000000000000000000000608482015260a40161028d565b60005460ff1615610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a2045636f746f6e6520616c72656164792060448201527f6163746976650000000000000000000000000000000000000000000000000000606482015260840161028d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000805460ff161561055c57610556826108b4565b92915050565b61055682610958565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff166368d5dca66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610d04565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663c59859186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b6000806106b883610ab4565b60005490915060ff16156106cc5792915050565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561072b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074f9190610cb5565b6107599082610d59565b9392505050565b6000805460ff16156107f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a207363616c61722829206973206465707260448201527f6563617465640000000000000000000000000000000000000000000000000000606482015260840161028d565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663f82061406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b6000806108c083610ab4565b905060006108cc610565565b6108d461064b565b6108df906010610d71565b63ffffffff166108ef9190610d9d565b905060006108fb610853565b6109036105c6565b63ffffffff166109139190610d9d565b905060006109218284610d59565b61092b9085610d9d565b90506109396006600a610efa565b610944906010610d9d565b61094e9082610f06565b9695505050505050565b60008061096483610ab4565b9050600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109eb9190610cb5565b6109f3610565565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a769190610cb5565b610a809085610d59565b610a8a9190610d9d565b610a949190610d9d565b9050610aa26006600a610efa565b610aac9082610f06565b949350505050565b80516000908190815b81811015610b3757848181518110610ad757610ad7610f41565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016600003610b1757610b10600484610d59565b9250610b25565b610b22601084610d59565b92505b80610b2f81610f70565b915050610abd565b50610aac82610440610d59565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610b8557600080fd5b813567ffffffffffffffff80821115610b9d57600080fd5b818401915084601f830112610bb157600080fd5b813581811115610bc357610bc3610b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610c0957610c09610b44565b81604052828152876020848701011115610c2257600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b81811015610c6f57858101830151858201604001528201610c53565b81811115610c81576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610cc757600080fd5b5051919050565b600060208284031215610ce057600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461075957600080fd5b600060208284031215610d1657600080fd5b815163ffffffff8116811461075957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610d6c57610d6c610d2a565b500190565b600063ffffffff80831681851681830481118215151615610d9457610d94610d2a565b02949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610dd557610dd5610d2a565b500290565b600181815b80851115610e3357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610e1957610e19610d2a565b80851615610e2657918102915b93841c9390800290610ddf565b509250929050565b600082610e4a57506001610556565b81610e5757506000610556565b8160018114610e6d5760028114610e7757610e93565b6001915050610556565b60ff841115610e8857610e88610d2a565b50506001821b610556565b5060208310610133831016604e8410600b8410161715610eb6575081810a610556565b610ec08383610dda565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610ef257610ef2610d2a565b029392505050565b60006107598383610e3b565b600082610f3c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610fa157610fa1610d2a565b506001019056fea164736f6c634300080f000a"); + + // Deploy the L1 Block Contract + let mut buffer = Vec::new(); + OpTxEnvelope::Deposit(TxDeposit { + source_hash: DEPLOY_L1_BLOCK_SOURCE.source_hash(), + from: L1_BLOCK_DEPLOYER_ADDRESS, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 375_000, + is_system_transaction: false, + input: l1_block_deployment_bytecode, + }) + .encode(&mut buffer); + txs.push(RawTransaction::from(buffer)); + + // Deploy the Gas Price Oracle + buffer = Vec::new(); + OpTxEnvelope::Deposit(TxDeposit { + source_hash: DEPLOY_GAS_PRICE_ORACLE_SOURCE.source_hash(), + from: GAS_PRICE_ORACLE_DEPLOYER_ADDRESS, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 1_000_000, + is_system_transaction: false, + input: gas_price_oracle_deployment_bytecode, + }) + .encode(&mut buffer); + txs.push(RawTransaction::from(buffer)); + + // Update the l1 block proxy + buffer = Vec::new(); + OpTxEnvelope::Deposit(TxDeposit { + source_hash: UPDATE_L1_BLOCK_PROXY_SOURCE.source_hash(), + from: Address::default(), + to: TxKind::Call(L1_BLOCK_DEPLOYER_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 50_000, + is_system_transaction: false, + input: upgrade_to_calldata(NEW_L1_BLOCK_ADDRESS), + }) + .encode(&mut buffer); + txs.push(RawTransaction::from(buffer)); + + // Update gas price oracle proxy + buffer = Vec::new(); + OpTxEnvelope::Deposit(TxDeposit { + source_hash: UPDATE_GAS_PRICE_ORACLE_SOURCE.source_hash(), + from: Address::default(), + to: TxKind::Call(GAS_PRICE_ORACLE_DEPLOYER_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 50_000, + is_system_transaction: false, + input: upgrade_to_calldata(GAS_PRICE_ORACLE_ADDRESS), + }) + .encode(&mut buffer); + txs.push(RawTransaction::from(buffer)); + + // Enable ecotone + buffer = Vec::new(); + OpTxEnvelope::Deposit(TxDeposit { + source_hash: ENABLE_ECOTONE_SOURCE.source_hash(), + from: L1_BLOCK_DEPLOYER_ADDRESS, + to: TxKind::Call(GAS_PRICE_ORACLE_ADDRESS), + mint: 0.into(), + value: U256::ZERO, + gas_limit: 80_000, + is_system_transaction: false, + input: ENABLE_ECOTONE_INPUT.into(), + }) + .encode(&mut buffer); + txs.push(RawTransaction::from(buffer)); + + // Deploy EIP4788 + buffer = Vec::new(); + OpTxEnvelope::Deposit(TxDeposit { + source_hash: BEACON_ROOTS_SOURCE.source_hash(), + from: EIP4788_FROM, + to: TxKind::Create, + mint: 0.into(), + value: U256::ZERO, + gas_limit: 250_000, + is_system_transaction: false, + input: eip4788_creation_data, + }) + .encode(&mut buffer); + txs.push(RawTransaction::from(buffer)); + + Ok(txs) + } +} + diff --git a/src/derive/mod.rs b/src/derive/mod.rs index 667a05e..932778c 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -6,7 +6,7 @@ pub mod state; pub use state::State; pub mod ecotone_upgrade; -pub use ecotone_upgrade::get_ecotone_upgrade_transactions; +pub use ecotone_upgrade::EcotoneTransactionBuilder; pub mod purgeable; pub use purgeable::PurgeableIterator; diff --git a/src/derive/pipeline.rs b/src/derive/pipeline.rs index c9638c0..08c82c2 100644 --- a/src/derive/pipeline.rs +++ b/src/derive/pipeline.rs @@ -1,7 +1,7 @@ //! Contains the pipeline implementation. use alloy_primitives::Bytes; -use eyre::Result; +use anyhow::Result; use std::sync::{mpsc, Arc, RwLock}; use crate::{config::Config, engine::PayloadAttributes}; diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index a684f77..591ef3f 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -6,12 +6,12 @@ use alloy_primitives::{keccak256, Address, Bytes, B256, U256, U64}; use alloy_rlp::encode; use alloy_rlp::Encodable; -use eyre::Result; +use anyhow::Result; use crate::common::{Epoch, RawTransaction}; use crate::config::{Config, SystemAccounts}; use crate::derive::state::State; -use crate::derive::{get_ecotone_upgrade_transactions, PurgeableIterator}; +use crate::derive::{EcotoneTransactionBuilder, PurgeableIterator}; use crate::engine::PayloadAttributes; use crate::l1::L1Info; @@ -137,10 +137,10 @@ impl Attributes { if self .config .chain - .is_ecotone_activation_block(U64::from(input.timestamp)) + .is_ecotone_activation_block(&U64::from(input.timestamp)) { tracing::info!("found Ecotone activation block; Upgrade transactions added"); - let mut ecotone_upgrade_txs = get_ecotone_upgrade_transactions(); + let mut ecotone_upgrade_txs = EcotoneTransactionBuilder::build_txs().expect("Failed to build Ecotone upgrade transactions"); transactions.append(&mut ecotone_upgrade_txs); } @@ -410,7 +410,7 @@ impl UserDeposited { } impl TryFrom for UserDeposited { - type Error = eyre::Report; + type Error = anyhow::Report; /// Converts the emitted L1 deposit event log into [UserDeposited] fn try_from(log: alloy_rpc_types::Log) -> Result { @@ -431,24 +431,24 @@ impl TryFrom for UserDeposited { // ------------------------------------------------------------ let opaque_content_offset: U64 = - U64::try_from_be_slice(&log.data.data[24..32]).ok_or(eyre::eyre!( + U64::try_from_be_slice(&log.data.data[24..32]).ok_or(anyhow::anyhow!( "Invalid opaque data offset: {}:", Bytes::copy_from_slice(&log.data.data[24..32]) ))?; if opaque_content_offset != U64::from(32) { - eyre::bail!("Invalid opaque data offset: {}", opaque_content_offset); + anyhow::bail!("Invalid opaque data offset: {}", opaque_content_offset); } // The next 32 bytes indicate the length of the opaqueData content. let opaque_content_len = u64::from_be_bytes(log.data.data[56..64].try_into().map_err(|_| { - eyre::eyre!( + anyhow::anyhow!( "Invalid opaque data length: {}", Bytes::copy_from_slice(&log.data.data[56..64]) ) })?); if opaque_content_len as usize > log.data.data.len() - 64 { - eyre::bail!( + anyhow::bail!( "Invalid opaque data length: {} exceeds log data length: {}", opaque_content_len, log.data.data.len() - 64 @@ -456,9 +456,9 @@ impl TryFrom for UserDeposited { } let padded_len = opaque_content_len .checked_add(32) - .ok_or(eyre::eyre!("Opaque data overflow: {}", opaque_content_len))?; + .ok_or(anyhow::anyhow!("Opaque data overflow: {}", opaque_content_len))?; if padded_len as usize <= log.data.data.len() - 64 { - eyre::bail!( + anyhow::bail!( "Opaque data with len {} overflows padded length {}", log.data.data.len() - 64, opaque_content_len @@ -476,9 +476,9 @@ impl TryFrom for UserDeposited { let is_creation = opaque_data[72] != 0; let data = opaque_data[73..].to_vec(); - let l1_block_num = log.block_number.ok_or(eyre::eyre!("block num not found"))?; + let l1_block_num = log.block_number.ok_or(anyhow::anyhow!("block num not found"))?; - let l1_block_hash = log.block_hash.ok_or(eyre::eyre!("block hash not found"))?; + let l1_block_hash = log.block_hash.ok_or(anyhow::anyhow!("block hash not found"))?; let log_index = U256::from(log.log_index.unwrap()); Ok(Self { diff --git a/src/derive/stages/batcher_transactions.rs b/src/derive/stages/batcher_transactions.rs index 8fe08ce..6fe0f80 100644 --- a/src/derive/stages/batcher_transactions.rs +++ b/src/derive/stages/batcher_transactions.rs @@ -3,7 +3,7 @@ use std::sync::mpsc; use alloy_primitives::Bytes; -use eyre::Result; +use anyhow::Result; use std::collections::VecDeque; use crate::derive::PurgeableIterator; @@ -82,7 +82,7 @@ impl BatcherTransaction { /// Creates a new [BatcherTransaction] pub fn new(data: &[u8], l1_origin: u64) -> Result { let version = data[0]; - let frame_data = data.get(1..).ok_or(eyre::eyre!("No frame data"))?; + let frame_data = data.get(1..).ok_or(anyhow::anyhow!("No frame data"))?; let mut offset = 0; let mut frames = Vec::new(); @@ -119,7 +119,7 @@ impl Frame { let data = &data[offset..]; if data.len() < 23 { - eyre::bail!("invalid frame size"); + anyhow::bail!("invalid frame size"); } let channel_id = u128::from_be_bytes(data[0..16].try_into()?); @@ -128,13 +128,13 @@ impl Frame { let frame_data_end = 22 + frame_data_len as usize; if data.len() < frame_data_end { - eyre::bail!("invalid frame size"); + anyhow::bail!("invalid frame size"); } let frame_data = data[22..frame_data_end].to_vec(); let is_last = if data[frame_data_end] > 1 { - eyre::bail!("invalid is_last flag"); + anyhow::bail!("invalid is_last flag"); } else { data[frame_data_end] != 0 }; diff --git a/src/derive/stages/batches.rs b/src/derive/stages/batches.rs index fcd75f4..2b3dafc 100644 --- a/src/derive/stages/batches.rs +++ b/src/derive/stages/batches.rs @@ -8,7 +8,7 @@ use std::collections::BTreeMap; use std::io::Read; use std::sync::{Arc, RwLock}; -use eyre::Result; +use anyhow::Result; use libflate::zlib::Decoder; use crate::config::Config; @@ -439,7 +439,7 @@ fn decode_batches(channel: &Channel, chain_id: u64) -> Result> { let rlp = Rlp::new(batch_content); let size = rlp .get_next::()? - .ok_or_else(|| eyre::eyre!("failed to get header"))? + .ok_or_else(|| anyhow::anyhow!("failed to get header"))? .len(); let mut batch = SingleBatch::decode(&mut batch_content)?; @@ -453,7 +453,7 @@ fn decode_batches(channel: &Channel, chain_id: u64) -> Result> { batches.push(Batch::Span(batch)); break; } - _ => eyre::bail!("invalid batch version"), + _ => anyhow::bail!("invalid batch version"), }; } diff --git a/src/derive/stages/block_input.rs b/src/derive/stages/block_input.rs index 3038739..38292f1 100644 --- a/src/derive/stages/block_input.rs +++ b/src/derive/stages/block_input.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock}; -use eyre::Result; +use anyhow::Result; use crate::{ common::{Epoch, RawTransaction}, @@ -32,10 +32,10 @@ pub struct BlockInput { impl BlockInput { /// Returns the [BlockInput] with full [Epoch] details. pub fn with_full_epoch(self, state: &Arc>) -> Result> { - let state = state.read().map_err(|_| eyre::eyre!("lock poisoned"))?; + let state = state.read().map_err(|_| anyhow::anyhow!("lock poisoned"))?; let epoch = state .epoch_by_number(self.epoch) - .ok_or(eyre::eyre!("epoch not found"))?; + .ok_or(anyhow::anyhow!("epoch not found"))?; Ok(BlockInput { timestamp: self.timestamp, diff --git a/src/derive/stages/span_batch.rs b/src/derive/stages/span_batch.rs index 004ade6..db08420 100644 --- a/src/derive/stages/span_batch.rs +++ b/src/derive/stages/span_batch.rs @@ -1,8 +1,9 @@ //! Module to handle [SpanBatch] decoding and processing. +use alloy_rlp::Rlp; use alloy_primitives::{Address, Bytes, U256}; use alloy_rpc_types::transaction::AccessList; -use eyre::Result; +use anyhow::Result; use crate::{common::RawTransaction, config::Config}; @@ -456,6 +457,7 @@ fn decode_u256(data: &[u8]) -> (U256, &[u8]) { mod test { use std::io::Read; + use alloy_rlp::Rlp; use alloy_primitives::keccak256; use libflate::zlib::Decoder; @@ -512,8 +514,6 @@ mod test { assert_eq!(batch.l1_inclusion_block, 0); - println!("starting epoch: {}", batch.start_epoch_num()); - let inputs = batch.block_inputs(&config); inputs.iter().for_each(|input| { let block_number = (input.timestamp - config.chain.l2_genesis.timestamp) / 2; @@ -522,7 +522,5 @@ mod test { println!("{:?}", keccak256(&tx.0)); }); }); - - // println!("{:?}", batch.block_inputs(&config)) } } diff --git a/src/derive/state.rs b/src/derive/state.rs index 6a6ada5..b30604a 100644 --- a/src/derive/state.rs +++ b/src/derive/state.rs @@ -15,6 +15,7 @@ use crate::{ /// Represents the current derivation state. /// Consists of cached L1 & L2 blocks, and details of the current safe head & safe epoch. +#[derive(Debug)] pub struct State { /// Map of L1 blocks from the current L1 safe epoch - ``seq_window_size`` l1_info: BTreeMap, diff --git a/src/driver/engine_driver.rs b/src/driver/engine_driver.rs index 38ddacc..1af08d4 100644 --- a/src/driver/engine_driver.rs +++ b/src/driver/engine_driver.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use alloy_primitives::keccak256; use alloy_provider::{Provider, ReqwestProvider}; use alloy_rpc_types::{Block, BlockTransactions}; -use eyre::Result; +use anyhow::Result; use crate::{ common::{BlockInfo, Epoch}, @@ -132,12 +132,12 @@ impl EngineDriver { .await?; if update.payload_status.status != Status::Valid { - eyre::bail!("invalid payload attributes"); + anyhow::bail!("invalid payload attributes"); } let id = update .payload_id - .ok_or(eyre::eyre!("engine did not return payload id"))?; + .ok_or(anyhow::anyhow!("engine did not return payload id"))?; self.engine.get_payload(id).await } @@ -146,7 +146,7 @@ impl EngineDriver { async fn push_payload(&self, payload: ExecutionPayload) -> Result<()> { let status = self.engine.new_payload(payload).await?; if status.status != Status::Valid && status.status != Status::Accepted { - eyre::bail!("invalid execution payload"); + anyhow::bail!("invalid execution payload"); } Ok(()) @@ -158,7 +158,7 @@ impl EngineDriver { let update = self.engine.forkchoice_updated(forkchoice, None).await?; if update.payload_status.status != Status::Valid { - eyre::bail!( + anyhow::bail!( "could not accept new forkchoice: {:?}", update.payload_status.validation_error ); diff --git a/src/driver/info.rs b/src/driver/info.rs index fa583a2..15105b5 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -5,7 +5,7 @@ use crate::driver::types::HeadInfo; use alloy_provider::Provider; use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag}; -use eyre::Result; +use anyhow::Result; /// An asynchronous trait for fetching blocks along with their transactions. #[async_trait::async_trait] diff --git a/src/driver/node_driver.rs b/src/driver/node_driver.rs index b6c1eac..486c787 100644 --- a/src/driver/node_driver.rs +++ b/src/driver/node_driver.rs @@ -9,7 +9,7 @@ use std::{ use alloy_primitives::Address; use alloy_provider::ProviderBuilder; -use eyre::Result; +use anyhow::Result; use reqwest::Url; use tokio::{ sync::watch::{self, Sender}, @@ -172,16 +172,16 @@ impl NodeDriver { for next_attributes in self.pipeline.by_ref() { let l1_inclusion_block = next_attributes .l1_inclusion_block - .ok_or(eyre::eyre!("attributes without inclusion block"))?; + .ok_or(anyhow::anyhow!("attributes without inclusion block"))?; let seq_number = next_attributes .seq_number - .ok_or(eyre::eyre!("attributes without seq number"))?; + .ok_or(anyhow::anyhow!("attributes without seq number"))?; self.engine_driver .handle_attributes(next_attributes) .await - .map_err(|e| eyre::eyre!("failed to handle attributes: {}", e))?; + .map_err(|e| anyhow::anyhow!("failed to handle attributes: {}", e))?; tracing::info!( "safe head updated: {} {:?}", @@ -194,7 +194,7 @@ impl NodeDriver { self.state .write() - .map_err(|_| eyre::eyre!("lock poisoned"))? + .map_err(|_| anyhow::anyhow!("lock poisoned"))? .update_safe_head(new_safe_head, new_safe_epoch); let unfinalized_entry = ( @@ -243,7 +243,7 @@ impl NodeDriver { let mut state = self .state .write() - .map_err(|_| eyre::eyre!("lock poisoned"))?; + .map_err(|_| anyhow::anyhow!("lock poisoned"))?; state.update_safe_head(self.engine_driver.safe_head, self.engine_driver.safe_epoch); @@ -271,7 +271,7 @@ impl NodeDriver { self.state .write() - .map_err(|_| eyre::eyre!("lock poisoned"))? + .map_err(|_| anyhow::anyhow!("lock poisoned"))? .update_l1_info(*l1_info); } BlockUpdate::Reorg => { @@ -289,7 +289,7 @@ impl NodeDriver { self.state .write() - .map_err(|_| eyre::eyre!("lock poisoned"))? + .map_err(|_| anyhow::anyhow!("lock poisoned"))? .purge( self.engine_driver.finalized_head, self.engine_driver.finalized_epoch, @@ -361,7 +361,7 @@ mod tests { use alloy_provider::Provider; use alloy_rpc_types::{BlockId, BlockNumberOrTag}; - use eyre::Result; + use anyhow::Result; use tokio::sync::watch::channel; use crate::config::{ChainConfig, CliConfig}; diff --git a/src/driver/types.rs b/src/driver/types.rs index 8cc9d52..8031c76 100644 --- a/src/driver/types.rs +++ b/src/driver/types.rs @@ -1,7 +1,7 @@ //! A module to handle conversions to a [HeadInfo] struct. use alloy_rpc_types::{Block, BlockTransactions}; -use eyre::Result; +use anyhow::Result; use serde::{Deserialize, Serialize}; use crate::{ @@ -39,12 +39,12 @@ impl HeadInfo { /// This function is used when the L2 block is from the Bedrock hardfork or earlier. pub fn try_from_bedrock_block(block: Block) -> Result { let BlockTransactions::Full(txs) = block.transactions else { - return Err(eyre::eyre!( + return Err(anyhow::anyhow!( "Could not find the L1 attributes deposited transaction" )); }; let Some(first_tx) = txs.first() else { - return Err(eyre::eyre!( + return Err(anyhow::anyhow!( "Could not find the L1 attributes deposited transaction" )); }; @@ -63,12 +63,12 @@ impl HeadInfo { /// This function is used when the L2 block is from the Ecotone hardfork or later. pub fn try_from_ecotone_block(block: Block) -> Result { let BlockTransactions::Full(txs) = block.transactions else { - return Err(eyre::eyre!( + return Err(anyhow::anyhow!( "Could not find the L1 attributes deposited transaction" )); }; let Some(first_tx) = txs.first() else { - return Err(eyre::eyre!( + return Err(anyhow::anyhow!( "Could not find the L1 attributes deposited transaction" )); }; @@ -91,7 +91,7 @@ mod tests { use alloy_primitives::b256; use alloy_provider::{Provider, ProviderBuilder}; use alloy_rpc_types::Block; - use eyre::Result; + use anyhow::Result; #[test] fn should_fail_conversion_from_a_block_to_head_info_if_missing_l1_deposited_tx( @@ -221,10 +221,10 @@ mod tests { #[tokio::test] async fn test_head_info_from_l2_block_hash() -> Result<()> { let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { - eyre::bail!("L1_TEST_RPC_URL is not set"); + anyhow::bail!("L1_TEST_RPC_URL is not set"); }; let Ok(l2_rpc_url) = std::env::var("L2_TEST_RPC_URL") else { - eyre::bail!("L2_TEST_RPC_URL is not set"); + anyhow::bail!("L2_TEST_RPC_URL is not set"); }; let l2_block_hash = @@ -270,15 +270,15 @@ mod tests { use crate::driver::HeadInfo; use alloy_primitives::b256; use alloy_provider::{Provider, ProviderBuilder}; - use eyre::Result; + use anyhow::Result; #[tokio::test] async fn test_head_info_from_l2_block_hash() -> Result<()> { let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { - eyre::bail!("L1_TEST_RPC_URL is not set"); + anyhow::bail!("L1_TEST_RPC_URL is not set"); }; let Ok(l2_rpc_url) = std::env::var("L2_TEST_RPC_URL") else { - eyre::bail!("L2_TEST_RPC_URL is not set"); + anyhow::bail!("L2_TEST_RPC_URL is not set"); }; let l2_block_hash = diff --git a/src/engine/api.rs b/src/engine/api.rs index c912467..2821e9a 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::time::{Duration, SystemTime}; use again::RetryPolicy; -use eyre::Result; +use anyhow::Result; use futures::prelude::*; use futures_timer::TryFutureExt; use reqwest::{header, Client}; @@ -130,7 +130,7 @@ impl EngineApi { let client = self .client .as_ref() - .ok_or(eyre::eyre!("Driver missing http client"))?; + .ok_or(anyhow::anyhow!("Driver missing http client"))?; // Clone the secret so we can use it in the retry policy. let secret_clone = self.secret.clone(); @@ -144,7 +144,7 @@ impl EngineApi { let claims = secret_clone.generate_claims(Some(SystemTime::now())); let jwt = secret_clone .encode(&claims) - .map_err(|_| eyre::eyre!("EngineApi failed to encode jwt with claims!"))?; + .map_err(|_| anyhow::anyhow!("EngineApi failed to encode jwt with claims!"))?; // Send the request client @@ -152,13 +152,13 @@ impl EngineApi { .header(header::AUTHORIZATION, format!("Bearer {}", jwt)) .json(&body) .send() - .map_err(|e| eyre::eyre!(e)) + .map_err(|e| anyhow::anyhow!(e)) .timeout(Duration::from_secs(2)) .await? .json::>() - .map_err(|e| eyre::eyre!(e)) + .map_err(|e| anyhow::anyhow!(e)) .timeout(Duration::from_secs(2)) - .map_err(|e| eyre::eyre!(e)) + .map_err(|e| anyhow::anyhow!(e)) .await }) .await?; @@ -168,11 +168,11 @@ impl EngineApi { } if let Some(err) = res.error { - eyre::bail!("Engine API POST error: {}", err.message); + anyhow::bail!("Engine API POST error: {}", err.message); } // This scenario shouldn't occur as the response should always have either data or an error - eyre::bail!("Failed to parse Engine API response") + anyhow::bail!("Failed to parse Engine API response") } /// Calls the engine to verify it's available to receive requests diff --git a/src/engine/auth.rs b/src/engine/auth.rs index e008eeb..16da142 100644 --- a/src/engine/auth.rs +++ b/src/engine/auth.rs @@ -2,7 +2,7 @@ //! //! This module was built using [reth](https://github.com/paradigmxyz/reth). -use eyre::Result; +use anyhow::Result; use jsonwebtoken::Algorithm; use rand::Rng; use serde::{Deserialize, Serialize}; @@ -29,7 +29,7 @@ impl JwtSecret { pub fn from_hex>(hex: S) -> Result { let hex: &str = hex.as_ref().trim(); if hex.len() != JWT_SECRET_LEN { - Err(eyre::eyre!("Invalid JWT secret key length.")) + Err(anyhow::anyhow!("Invalid JWT secret key length.")) } else { let hex_bytes = hex::decode(hex)?; let bytes = hex_bytes.try_into().expect("is expected len"); diff --git a/src/engine/mock_engine.rs b/src/engine/mock_engine.rs index 6833491..912ae39 100644 --- a/src/engine/mock_engine.rs +++ b/src/engine/mock_engine.rs @@ -1,7 +1,7 @@ //! A mock L2 Engine API. use async_trait::async_trait; -use eyre::Result; +use anyhow::Result; use super::{ Engine, ExecutionPayload, ForkChoiceUpdate, ForkchoiceState, PayloadAttributes, PayloadId, diff --git a/src/engine/payload.rs b/src/engine/payload.rs index ca2e54a..e46ba16 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -1,11 +1,11 @@ //! Payload types for the L2 execution engine. -use alloy_consensus::TxEnvelope; +use op_alloy_consensus::OpTxEnvelope; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::{Address, Bytes, B256, U64}; use alloy_rpc_types::Block; use alloy_rpc_types::BlockTransactions; -use eyre::Result; +use anyhow::Result; use serde::{Deserialize, Serialize}; use crate::{ @@ -57,19 +57,19 @@ pub struct ExecutionPayload { } impl TryFrom for ExecutionPayload { - type Error = eyre::Report; + type Error = anyhow::Error; /// Converts a [Block] to an [ExecutionPayload] fn try_from(value: Block) -> Result { let txs = if let BlockTransactions::Full(txs) = value.transactions { txs } else { - return Err(eyre::eyre!("Expected full transactions")); + return Err(anyhow::anyhow!("Expected full transactions")); }; let encoded_txs = (txs .into_iter() .map(|tx| { - let envelope: TxEnvelope = tx.try_into().unwrap(); + let envelope: OpTxEnvelope = tx.try_into().unwrap(); let encoded = envelope.encoded_2718(); RawTransaction(encoded.to_vec()) }) @@ -85,11 +85,11 @@ impl TryFrom for ExecutionPayload { prev_randao: value .header .mix_hash - .ok_or_else(|| eyre::eyre!("Missing mix hash"))?, + .ok_or_else(|| anyhow::anyhow!("Missing mix hash"))?, block_number: value .header .number - .ok_or_else(|| eyre::eyre!("Missing block number"))? + .ok_or_else(|| anyhow::anyhow!("Missing block number"))? .try_into()?, gas_limit: (value.header.gas_limit as u64).try_into()?, gas_used: (value.header.gas_used as u64).try_into()?, @@ -100,7 +100,7 @@ impl TryFrom for ExecutionPayload { block_hash: value .header .hash - .ok_or_else(|| eyre::eyre!("Missing block hash"))?, + .ok_or_else(|| anyhow::anyhow!("Missing block hash"))?, transactions: encoded_txs, withdrawals: Some(Vec::new()), blob_gas_used: value @@ -198,7 +198,7 @@ mod tests { use crate::engine::ExecutionPayload; use alloy_primitives::{b256, uint}; use alloy_provider::{Provider, ProviderBuilder}; - use eyre::Result; + use anyhow::Result; #[tokio::test] async fn test_from_block_hash_to_execution_paylaod() -> Result<()> { diff --git a/src/engine/traits.rs b/src/engine/traits.rs index dc2a317..2663350 100644 --- a/src/engine/traits.rs +++ b/src/engine/traits.rs @@ -1,7 +1,7 @@ //! Core [Engine] trait for the Engine API. use async_trait::async_trait; -use eyre::Result; +use anyhow::Result; use super::{ ExecutionPayload, ForkChoiceUpdate, ForkchoiceState, PayloadAttributes, PayloadId, diff --git a/src/l1/blob_encoding.rs b/src/l1/blob_encoding.rs index 6ca2c32..59a41aa 100644 --- a/src/l1/blob_encoding.rs +++ b/src/l1/blob_encoding.rs @@ -1,7 +1,7 @@ //! Blob decoding module. use alloy_primitives::Bytes; -use eyre::Result; +use anyhow::Result; const MAX_BLOB_DATA_SIZE: usize = (4 * 31 + 3) * 1024 - 4; const ENCODING_VERSION: u8 = 0; @@ -13,7 +13,7 @@ pub fn decode_blob_data(blob: &[u8]) -> Result { let mut output = vec![0; MAX_BLOB_DATA_SIZE]; if blob[VERSION_OFFSET] != ENCODING_VERSION { - eyre::bail!( + anyhow::bail!( "Blob decoding: Invalid encoding version: want {}, got {}", ENCODING_VERSION, blob[VERSION_OFFSET] @@ -23,7 +23,7 @@ pub fn decode_blob_data(blob: &[u8]) -> Result { // decode the 3-byte big-endian length value into a 4-byte integer let output_len = u32::from_be_bytes([0, blob[2], blob[3], blob[4]]) as usize; if output_len > MAX_BLOB_DATA_SIZE { - eyre::bail!( + anyhow::bail!( "Blob decoding: Invalid length: {} exceeds maximum {}", output_len, MAX_BLOB_DATA_SIZE @@ -57,7 +57,7 @@ pub fn decode_blob_data(blob: &[u8]) -> Result { for output_byte in output.iter().take(MAX_BLOB_DATA_SIZE).skip(output_len) { if output_byte != &0 { - eyre::bail!( + anyhow::bail!( "Blob decoding: Extraneous data in field element {}", output_pos / 32 ); @@ -68,7 +68,7 @@ pub fn decode_blob_data(blob: &[u8]) -> Result { for byte in blob.iter().skip(input_pos) { if byte != &0 { - eyre::bail!( + anyhow::bail!( "Blob decoding: Extraneous data in input position {}", input_pos ); @@ -88,7 +88,7 @@ fn decode_field_element( // two highest order bits of the first byte of each field element should always be 0 if result & 0b1100_0000 != 0 { - eyre::bail!("Blob decoding: Invalid field element"); + anyhow::bail!("Blob decoding: Invalid field element"); } output[*output_pos..*output_pos + 31].copy_from_slice(&blob[*input_pos + 1..*input_pos + 32]); diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index 8b93e73..3124d3e 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -2,7 +2,7 @@ use std::sync::atomic::{AtomicU64, Ordering}; -use eyre::Result; +use anyhow::Result; use serde::Deserialize; use serde_json::Value; @@ -62,13 +62,13 @@ impl BlobFetcher { let spec = self.fetch_beacon_spec().await?; seconds_per_slot = spec .get("SECONDS_PER_SLOT") - .ok_or(eyre::eyre!("No seconds per slot in beacon spec"))? + .ok_or(anyhow::anyhow!("No seconds per slot in beacon spec"))? .as_str() - .ok_or(eyre::eyre!("Seconds per slot: expected string"))? + .ok_or(anyhow::anyhow!("Seconds per slot: expected string"))? .parse::()?; if seconds_per_slot == 0 { - eyre::bail!("Seconds per slot is 0; cannot calculate slot number"); + anyhow::bail!("Seconds per slot is 0; cannot calculate slot number"); } self.seconds_per_slot @@ -76,7 +76,7 @@ impl BlobFetcher { } if time < genesis_timestamp { - eyre::bail!("Time is before genesis; cannot calculate slot number"); + anyhow::bail!("Time is before genesis; cannot calculate slot number"); } Ok((time - genesis_timestamp) / seconds_per_slot) @@ -89,7 +89,7 @@ impl BlobFetcher { let res = self.client.get(full_url).send().await?.error_for_status()?; let res = serde_json::from_slice::(&res.bytes().await?)?; - let res = res.get("data").ok_or(eyre::eyre!("No data in response"))?; + let res = res.get("data").ok_or(anyhow::anyhow!("No data in response"))?; let blobs = serde_json::from_value::>(res.clone())?; @@ -102,10 +102,10 @@ impl BlobFetcher { let res = self.client.get(base_url).send().await?.error_for_status()?; let res = serde_json::from_slice::(&res.bytes().await?)?; - let res = res.get("data").ok_or(eyre::eyre!("No data in response"))?; - let res = res.get("genesis_time").ok_or(eyre::eyre!("No time"))?; + let res = res.get("data").ok_or(anyhow::anyhow!("No data in response"))?; + let res = res.get("genesis_time").ok_or(anyhow::anyhow!("No time"))?; - let genesis_time = res.as_str().ok_or(eyre::eyre!("Expected string"))?; + let genesis_time = res.as_str().ok_or(anyhow::anyhow!("Expected string"))?; let genesis_time = genesis_time.parse::()?; Ok(genesis_time) @@ -117,7 +117,7 @@ impl BlobFetcher { let res = self.client.get(base_url).send().await?.error_for_status()?; let res = serde_json::from_slice::(&res.bytes().await?)?; - let res = res.get("data").ok_or(eyre::eyre!("No data in response"))?; + let res = res.get("data").ok_or(anyhow::anyhow!("No data in response"))?; Ok(res.clone()) } diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index f31ba80..b09b21e 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -2,11 +2,11 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; -use eyre::Result; +use anyhow::Result; use once_cell::sync::Lazy; use tokio::{spawn, sync::mpsc, task::JoinHandle, time::sleep}; -use alloy_primitives::{keccak256, Address, Bytes, B256}; +use alloy_primitives::{keccak256, U256, Address, Bytes, B256}; use alloy_provider::{Provider, ProviderBuilder, ReqwestProvider}; use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag, BlockTransactions, Filter, Transaction}; @@ -149,9 +149,9 @@ impl ChainWatcher { let receiver = self .block_update_receiver .as_mut() - .ok_or(eyre::eyre!("the watcher hasn't started"))?; + .ok_or(anyhow::anyhow!("the watcher hasn't started"))?; - receiver.try_recv().map_err(eyre::Report::from) + receiver.try_recv().map_err(anyhow::Error::from) } /// Asynchronously receives from the block update channel. @@ -202,7 +202,7 @@ impl InnerWatcher { let batch_sender = alloy_primitives::Address::from_slice(&input[176..196]); let l1_fee_overhead = alloy_primitives::U256::from_be_slice(&input[196..228]); let l1_fee_scalar = alloy_primitives::U256::from_be_slice(&input[228..260]); - let gas_lim_slice = block.header.gas_limit.to_be_bytes(); + let gas_lim_slice: [u8; 32] = block.header.gas_limit.to_be_bytes(); let gas_limit = alloy_primitives::U256::from_be_slice(&gas_lim_slice); SystemConfig { @@ -362,7 +362,7 @@ impl InnerWatcher { } } - async fn get_finalized(&self) -> Result { + async fn get_finalized(&self) -> Result { let block_number = match self.config.devnet { false => BlockNumberOrTag::Finalized, true => BlockNumberOrTag::Latest, @@ -371,27 +371,27 @@ impl InnerWatcher { self.provider .get_block(BlockId::Number(block_number), false) .await? - .ok_or(eyre::eyre!("block not found"))? + .ok_or(anyhow::anyhow!("block not found"))? .header .number - .ok_or(eyre::eyre!("block pending")) + .ok_or(anyhow::anyhow!("block pending")) } - async fn get_head(&self) -> Result { + async fn get_head(&self) -> Result { self.provider .get_block(BlockId::Number(BlockNumberOrTag::Latest), false) .await? - .ok_or(eyre::eyre!("block not found"))? + .ok_or(anyhow::anyhow!("block not found"))? .header .number - .ok_or(eyre::eyre!("block pending")) + .ok_or(anyhow::anyhow!("block pending")) } async fn get_block(&self, block_num: u64) -> Result { self.provider .get_block(BlockId::Number(BlockNumberOrTag::Number(block_num)), true) .await? - .ok_or(eyre::eyre!("block not found")) + .ok_or(anyhow::anyhow!("block not found")) } async fn get_deposits(&mut self, block_num: u64) -> Result> { @@ -441,7 +441,7 @@ impl InnerWatcher { let full_txs = if let BlockTransactions::Full(txs) = &block.transactions { txs } else { - eyre::bail!("expected full transactions"); + anyhow::bail!("expected full transactions"); }; for tx in full_txs.iter() { @@ -486,7 +486,7 @@ impl InnerWatcher { let Some(blob_sidecar) = blobs.iter().find(|b| b.index == blob_index as u64) else { // This can happen in the case the blob retention window has expired // and the data is no longer available. This case is not handled yet. - eyre::bail!("blob index {} not found in fetched sidecars", blob_index); + anyhow::bail!("blob index {} not found in fetched sidecars", blob_index); }; // decode the full blob @@ -513,7 +513,9 @@ fn generate_http_provider(url: &str) -> Arc { let Ok(url) = reqwest::Url::parse(url) else { panic!("unable to parse url: {}", url); }; - let provider = ProviderBuilder::new().on_http(url); + let Ok(provider) = ProviderBuilder::new().on_http(url) else { + panic!("unable to create provider for url: {}", url); + }; Arc::new(provider) } diff --git a/src/l1/config_updates.rs b/src/l1/config_updates.rs index c9e1257..bb66753 100644 --- a/src/l1/config_updates.rs +++ b/src/l1/config_updates.rs @@ -2,7 +2,7 @@ use alloy_primitives::{Address, U256, U64}; use alloy_rpc_types::Log; -use eyre::Result; +use anyhow::Result; /// Represents a system config update event #[derive(Debug)] @@ -18,25 +18,25 @@ pub enum SystemConfigUpdate { } impl TryFrom for SystemConfigUpdate { - type Error = eyre::Report; + type Error = anyhow::Error; fn try_from(log: Log) -> Result { let version = U64::from_be_bytes( **log .topics() .get(1) - .ok_or(eyre::eyre!("invalid system config update"))?, + .ok_or(anyhow::anyhow!("invalid system config update"))?, ); if !version.is_zero() { - return Err(eyre::eyre!("invalid system config update")); + return Err(anyhow::anyhow!("invalid system config update")); } let update_type = U64::from_be_bytes( **log .topics() .get(2) - .ok_or(eyre::eyre!("invalid system config update"))?, + .ok_or(anyhow::anyhow!("invalid system config update"))?, ); let update_type: u64 = update_type.try_into()?; @@ -46,7 +46,7 @@ impl TryFrom for SystemConfigUpdate { .data() .data .get(76..96) - .ok_or(eyre::eyre!("invalid system config update"))?; + .ok_or(anyhow::anyhow!("invalid system config update"))?; let addr = Address::from_slice(addr_bytes); Ok(Self::BatchSender(addr)) @@ -56,13 +56,13 @@ impl TryFrom for SystemConfigUpdate { .data() .data .get(64..96) - .ok_or(eyre::eyre!("invalid system config update"))?; + .ok_or(anyhow::anyhow!("invalid system config update"))?; let fee_scalar = log .data() .data .get(96..128) - .ok_or(eyre::eyre!("invalid system config update"))?; + .ok_or(anyhow::anyhow!("invalid system config update"))?; let fee_overhead: [u8; 32] = fee_overhead.try_into()?; let fee_scalar: [u8; 32] = fee_scalar.try_into()?; @@ -76,7 +76,7 @@ impl TryFrom for SystemConfigUpdate { .data() .data .get(64..96) - .ok_or(eyre::eyre!("invalid system config update"))?; + .ok_or(anyhow::anyhow!("invalid system config update"))?; let gas_bytes: [u8; 32] = gas_bytes.try_into()?; let gas = U256::from_be_bytes(gas_bytes); @@ -87,12 +87,12 @@ impl TryFrom for SystemConfigUpdate { .data() .data .get(76..96) - .ok_or(eyre::eyre!("invalid system config update"))?; + .ok_or(anyhow::anyhow!("invalid system config update"))?; let addr = Address::from_slice(addr_bytes); Ok(Self::UnsafeBlockSigner(addr)) } - _ => Err(eyre::eyre!("invalid system config update")), + _ => Err(anyhow::anyhow!("invalid system config update")), } } } diff --git a/src/l1/l1_info.rs b/src/l1/l1_info.rs index cf82eff..73e210e 100644 --- a/src/l1/l1_info.rs +++ b/src/l1/l1_info.rs @@ -40,27 +40,27 @@ pub struct L1BlockInfo { } impl TryFrom<&Block> for L1BlockInfo { - type Error = eyre::Error; + type Error = anyhow::Error; fn try_from(value: &alloy_rpc_types::Block) -> std::result::Result { let number = value .header .number - .ok_or(eyre::eyre!("block not included"))?; + .ok_or(anyhow::anyhow!("block not included"))?; - let hash = value.header.hash.ok_or(eyre::eyre!("block not included"))?; + let hash = value.header.hash.ok_or(anyhow::anyhow!("block not included"))?; let timestamp = value.header.timestamp; let base_fee = value .header .base_fee_per_gas - .ok_or(eyre::eyre!("block is pre london"))?; + .ok_or(anyhow::anyhow!("block is pre london"))?; let mix_hash = value .header .mix_hash - .ok_or(eyre::eyre!("block not included"))?; + .ok_or(anyhow::anyhow!("block not included"))?; let parent_beacon_block_root = value.header.parent_beacon_block_root; diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index 9c2ffb9..261ce82 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -4,7 +4,7 @@ use std::sync::mpsc::{channel, Receiver, Sender}; use std::time::SystemTime; use alloy_primitives::{keccak256, Address, Bytes, Signature, B256, U64}; -use eyre::Result; +use anyhow::Result; use libp2p::gossipsub::{IdentTopic, Message, MessageAcceptance, TopicHash}; use ssz_rs::{prelude::*, List, Vector, U256}; use tokio::sync::watch; diff --git a/src/network/service/discovery.rs b/src/network/service/discovery.rs index 17a1205..697f7b5 100644 --- a/src/network/service/discovery.rs +++ b/src/network/service/discovery.rs @@ -7,7 +7,7 @@ use discv5::{ enr::{CombinedKey, Enr, EnrBuilder, NodeId}, Discv5, Discv5Config, }; -use eyre::Result; +use anyhow::Result; use tokio::{ sync::mpsc::{self, Receiver}, time::sleep, @@ -79,7 +79,7 @@ fn create_disc(chain_id: u64) -> Result { .build(&key)?; let config = Discv5Config::default(); - Discv5::new(enr, key, config).map_err(|_| eyre::eyre!("could not create disc service")) + Discv5::new(enr, key, config).map_err(|_| anyhow::anyhow!("could not create disc service")) } /// Default bootnodes to use. Currently consists of 2 Base bootnodes & 1 Optimism bootnode. diff --git a/src/network/service/enr.rs b/src/network/service/enr.rs index a10aeda..f4d2675 100644 --- a/src/network/service/enr.rs +++ b/src/network/service/enr.rs @@ -1,7 +1,7 @@ //! Contains the [OpStackEnrData] struct. use alloy_rlp::{Buf, Decodable, Encodable, Error}; -use eyre::Result; +use anyhow::Result; #[derive(Debug, Copy, Default, PartialEq, Clone)] pub struct OpStackEnrData { @@ -34,7 +34,7 @@ impl Encodable for OpStackEnrData { } impl TryFrom<&[u8]> for OpStackEnrData { - type Error = eyre::Report; + type Error = anyhow::Error; /// Converts a slice of RLP encoded bytes to [OpStackEnrData] fn try_from(mut value: &[u8]) -> Result { diff --git a/src/network/service/mod.rs b/src/network/service/mod.rs index 65b8be6..f90e3ea 100644 --- a/src/network/service/mod.rs +++ b/src/network/service/mod.rs @@ -2,7 +2,7 @@ use std::{net::SocketAddr, time::Duration}; -use eyre::Result; +use anyhow::Result; use futures::{prelude::*, select}; use libp2p::{ gossipsub::{self, IdentTopic, Message, MessageId}, @@ -67,7 +67,7 @@ impl Service { let multiaddr = Multiaddr::from(addr); swarm .listen_on(multiaddr) - .map_err(|_| eyre::eyre!("swarm listen failed"))?; + .map_err(|_| anyhow::anyhow!("swarm listen failed"))?; let mut handlers = Vec::new(); handlers.append(&mut self.handlers); @@ -166,11 +166,11 @@ impl Behaviour { .validate_messages() .message_id_fn(compute_message_id) .build() - .map_err(|_| eyre::eyre!("gossipsub config creation failed"))?; + .map_err(|_| anyhow::anyhow!("gossipsub config creation failed"))?; let mut gossipsub = gossipsub::Behaviour::new(gossipsub::MessageAuthenticity::Anonymous, gossipsub_config) - .map_err(|_| eyre::eyre!("gossipsub behaviour creation failed"))?; + .map_err(|_| anyhow::anyhow!("gossipsub behaviour creation failed"))?; handlers .iter() @@ -182,7 +182,7 @@ impl Behaviour { let topic = IdentTopic::new(topic.to_string()); gossipsub .subscribe(&topic) - .map_err(|_| eyre::eyre!("subscription failed")) + .map_err(|_| anyhow::anyhow!("subscription failed")) }) .collect::>() }) diff --git a/src/network/service/types.rs b/src/network/service/types.rs index d8f8cde..26f9665 100644 --- a/src/network/service/types.rs +++ b/src/network/service/types.rs @@ -2,7 +2,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use discv5::enr::{CombinedKey, Enr}; -use eyre::Result; +use anyhow::Result; use libp2p::{multiaddr::Protocol, Multiaddr}; /// An [Ipv4Addr] and port. @@ -22,12 +22,12 @@ pub struct Peer { } impl TryFrom<&Enr> for NetworkAddress { - type Error = eyre::Report; + type Error = anyhow::Error; /// Convert an [Enr] to a [NetworkAddress] fn try_from(value: &Enr) -> Result { - let ip = value.ip4().ok_or(eyre::eyre!("missing ip"))?; - let port = value.tcp4().ok_or(eyre::eyre!("missing port"))?; + let ip = value.ip4().ok_or(anyhow::anyhow!("missing ip"))?; + let port = value.tcp4().ok_or(anyhow::anyhow!("missing port"))?; Ok(Self { ip, port }) } @@ -52,13 +52,13 @@ impl From for SocketAddr { } impl TryFrom for NetworkAddress { - type Error = eyre::Report; + type Error = anyhow::Error; /// Converts a [SocketAddr] to a [NetworkAddress] fn try_from(value: SocketAddr) -> Result { let ip = match value.ip() { IpAddr::V4(ip) => ip, - IpAddr::V6(_) => eyre::bail!("ipv6 not supported"), + IpAddr::V6(_) => anyhow::bail!("ipv6 not supported"), }; Ok(Self { @@ -69,7 +69,7 @@ impl TryFrom for NetworkAddress { } impl TryFrom<&Enr> for Peer { - type Error = eyre::Report; + type Error = anyhow::Error; /// Converts an [Enr] to a [Peer] fn try_from(value: &Enr) -> Result { diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 6eadf89..00987f8 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -7,7 +7,7 @@ use crate::{ version::Version, }; -use eyre::Result; +use anyhow::Result; use alloy_primitives::{keccak256, B256}; use alloy_provider::{Provider, ProviderBuilder}; diff --git a/src/runner/mod.rs b/src/runner/mod.rs index cda8395..31fc7b1 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -7,7 +7,7 @@ use alloy_provider::ext::AdminApi; use alloy_provider::{Provider, ProviderBuilder, ReqwestProvider}; use alloy_rpc_types::{BlockId, BlockNumberOrTag, BlockTransactions, RpcBlockHash}; -use eyre::Result; +use anyhow::Result; use tokio::{ sync::watch::{channel, Receiver}, time::sleep, @@ -104,20 +104,20 @@ impl Runner { /// Note: the `admin` RPC method must be available on the execution client as checkpoint_sync relies on `admin_addPeer` pub async fn checkpoint_sync(&self) -> Result<()> { let l2_rpc_url = reqwest::Url::parse(&self.config.l2_rpc_url) - .map_err(|err| eyre::eyre!(format!("unable to parse l2_rpc_url: {err}")))?; + .map_err(|err| anyhow::anyhow!(format!("unable to parse l2_rpc_url: {err}")))?; let l2_provider = ProviderBuilder::new().on_http(l2_rpc_url); - let checkpoint_sync_url = self.config.checkpoint_sync_url.as_ref().ok_or(eyre::eyre!( + let checkpoint_sync_url = self.config.checkpoint_sync_url.as_ref().ok_or(anyhow::anyhow!( "checkpoint_sync_url is required for checkpoint sync mode" ))?; let checkpoint_sync_url = reqwest::Url::parse(checkpoint_sync_url) - .map_err(|err| eyre::eyre!(format!("unable to parse checkpoint_sync_url: {err}")))?; + .map_err(|err| anyhow::anyhow!(format!("unable to parse checkpoint_sync_url: {err}")))?; let checkpoint_sync_provider = ProviderBuilder::new().on_http(checkpoint_sync_url); let checkpoint_block = match self.checkpoint_hash { Some(ref checkpoint) => { let hash = B256::from_str(checkpoint) - .map_err(|_| eyre::eyre!("invalid checkpoint block hash provided"))?; + .map_err(|_| anyhow::anyhow!("invalid checkpoint block hash provided"))?; let block_hash = RpcBlockHash::from_hash(hash, None); let block_id = BlockId::Hash(block_hash); @@ -204,7 +204,7 @@ impl Runner { let checkpoint_block_num: u64 = checkpoint_payload .block_number .try_into() - .map_err(|_| eyre::eyre!("could not convert checkpoint block number to u64"))?; + .map_err(|_| anyhow::anyhow!("could not convert checkpoint block number to u64"))?; while l2_provider.get_block_number().await? < checkpoint_block_num { self.check_shutdown()?; sleep(Duration::from_secs(3)).await; @@ -247,7 +247,7 @@ impl Runner { let l2_block = checkpoint_sync_provider .get_block(block.into(), true) .await? - .ok_or_else(|| eyre::eyre!("could not find block"))?; + .ok_or_else(|| anyhow::anyhow!("could not find block"))?; let predeploy = SystemAccounts::default().attributes_predeploy; let full_txs = if let BlockTransactions::Full(txs) = l2_block.transactions { diff --git a/src/telemetry/metrics.rs b/src/telemetry/metrics.rs index d5019cc..b839ed6 100644 --- a/src/telemetry/metrics.rs +++ b/src/telemetry/metrics.rs @@ -1,6 +1,6 @@ //! Prometheus Metrics Module. -use eyre::{Result, WrapErr}; +use anyhow::Result; use lazy_static::lazy_static; use prometheus_exporter::{ prometheus::{register_int_gauge, IntGauge}, @@ -20,6 +20,8 @@ lazy_static! { /// Starts the metrics server on port 9200 pub fn init() -> Result<()> { - start("0.0.0.0:9200".parse().wrap_err("Could not parse address")?)?; - Ok(()) + match start("0.0.0.0:9200".parse()) { + Ok(_) => Ok(()), + Err(e) => Err(e.into()), + } }