From 7568231c9f95c6e4e68a62a594f461cf33ac788d Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 22 Jan 2024 23:17:14 +0100 Subject: [PATCH 01/23] chore: refactor l1 module --- src/l1/chain_watcher.rs | 449 +++++++++++++++++++++++++++ src/l1/config_updates.rs | 78 +++++ src/l1/l1_info.rs | 87 ++++++ src/l1/mod.rs | 646 +-------------------------------------- 4 files changed, 620 insertions(+), 640 deletions(-) create mode 100644 src/l1/chain_watcher.rs create mode 100644 src/l1/config_updates.rs create mode 100644 src/l1/l1_info.rs diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs new file mode 100644 index 00000000..902c9eed --- /dev/null +++ b/src/l1/chain_watcher.rs @@ -0,0 +1,449 @@ +use std::{collections::HashMap, sync::Arc, time::Duration}; + +use ethers::{ + providers::{Http, HttpRateLimitRetryPolicy, Middleware, Provider, RetryClient}, + types::{Address, Block, BlockNumber, Filter, Transaction, H256, U256}, + utils::keccak256, +}; +use eyre::Result; +use once_cell::sync::Lazy; +use reqwest::Url; +use tokio::{spawn, sync::mpsc, task::JoinHandle, time::sleep}; + +use crate::{ + common::BlockInfo, + config::{Config, SystemConfig}, + derive::stages::attributes::UserDeposited, +}; + +use super::{L1Info, SystemConfigUpdate}; + +static CONFIG_UPDATE_TOPIC: Lazy = + Lazy::new(|| H256::from_slice(&keccak256("ConfigUpdate(uint256,uint8,bytes)"))); + +static TRANSACTION_DEPOSITED_TOPIC: Lazy = Lazy::new(|| { + H256::from_slice(&keccak256( + "TransactionDeposited(address,address,uint256,bytes)", + )) +}); + +/// Handles watching the L1 chain and monitoring for new blocks, deposits, +/// and batcher transactions. The monitoring loop is spawned in a seperate +/// task and communication happens via the internal channels. When ChainWatcher +/// is dropped, the monitoring task is automatically aborted. +pub struct ChainWatcher { + /// Task handle for the monitoring loop + handle: Option>, + /// Global config + config: Arc, + /// The L1 starting block + l1_start_block: u64, + /// The L2 starting block + l2_start_block: u64, + /// Channel for receiving block updates for each new block + block_update_receiver: Option>, +} + +/// Updates L1Info +pub enum BlockUpdate { + /// A new block extending the current chain + NewBlock(Box), + /// Updates the most recent finalized block + FinalityUpdate(u64), + /// Reorg detected + Reorg, +} + +/// Watcher actually ingests the L1 blocks. Should be run in another +/// thread and called periodically to keep updating channels +struct InnerWatcher { + /// Global Config + config: Arc, + /// Ethers provider for L1 + provider: Arc>>, + /// Channel to send block updates + block_update_sender: mpsc::Sender, + /// Most recent ingested block + current_block: u64, + /// Most recent block + head_block: u64, + /// Most recent finalized block + finalized_block: u64, + /// List of blocks that have not been finalized yet + unfinalized_blocks: Vec, + /// Mapping from block number to user deposits. Past block deposits + /// are removed as they are no longer needed + deposits: HashMap>, + /// Current system config value + system_config: SystemConfig, + /// Next system config if it exists and the L1 block number it activates + system_config_update: (u64, Option), +} + +impl Drop for ChainWatcher { + fn drop(&mut self) { + if let Some(handle) = self.handle.take() { + handle.abort(); + } + } +} + +impl ChainWatcher { + /// Creates a new ChainWatcher and begins the monitoring task. + /// Errors if the rpc url in the config is invalid. + pub fn new(l1_start_block: u64, l2_start_block: u64, config: Arc) -> Result { + Ok(Self { + handle: None, + config, + l1_start_block, + l2_start_block, + block_update_receiver: None, + }) + } + + /// Starts the chain watcher at the given block numbers + pub fn start(&mut self) -> Result<()> { + if let Some(handle) = self.handle.take() { + handle.abort(); + } + + let (handle, recv) = start_watcher( + self.l1_start_block, + self.l2_start_block, + self.config.clone(), + )?; + + self.handle = Some(handle); + self.block_update_receiver = Some(recv); + + Ok(()) + } + + /// Resets the chain watcher at the given block numbers + pub fn restart(&mut self, l1_start_block: u64, l2_start_block: u64) -> Result<()> { + if let Some(handle) = self.handle.take() { + handle.abort(); + } + + let (handle, recv) = start_watcher(l1_start_block, l2_start_block, self.config.clone())?; + + self.handle = Some(handle); + self.block_update_receiver = Some(recv); + self.l1_start_block = l1_start_block; + self.l2_start_block = l2_start_block; + + Ok(()) + } + + /// Attempts to receive a message from the block update channel. + /// Returns an error if the channel contains no messages. + pub fn try_recv_from_channel(&mut self) -> Result { + let receiver = self + .block_update_receiver + .as_mut() + .ok_or(eyre::eyre!("the watcher hasn't started"))?; + + receiver.try_recv().map_err(eyre::Report::from) + } + + /// Asynchronously receives from the block update channel. + /// Returns `None` if the channel contains no messages. + pub async fn recv_from_channel(&mut self) -> Option { + match &mut self.block_update_receiver { + Some(receiver) => receiver.recv().await, + None => None, + } + } +} + +impl InnerWatcher { + async fn new( + config: Arc, + block_update_sender: mpsc::Sender, + l1_start_block: u64, + l2_start_block: u64, + ) -> Self { + let provider = generate_http_provider(&config.l1_rpc_url); + + let system_config = if l2_start_block == config.chain.l2_genesis.number { + config.chain.system_config + } else { + let l2_provider = generate_http_provider(&config.l2_rpc_url); + + let block = l2_provider + .get_block_with_txs(l2_start_block - 1) + .await + .unwrap() + .unwrap(); + + let input = &block + .transactions + .first() + .expect( + "Could not find the L1 attributes deposited transaction in the parent L2 block", + ) + .input; + + let batch_sender = Address::from_slice(&input[176..196]); + let l1_fee_overhead = U256::from(H256::from_slice(&input[196..228]).as_bytes()); + let l1_fee_scalar = U256::from(H256::from_slice(&input[228..260]).as_bytes()); + + SystemConfig { + batch_sender, + l1_fee_overhead, + l1_fee_scalar, + gas_limit: block.gas_limit, + // TODO: fetch from contract + unsafe_block_signer: config.chain.system_config.unsafe_block_signer, + } + }; + + Self { + config, + provider, + block_update_sender, + current_block: l1_start_block, + head_block: 0, + finalized_block: 0, + unfinalized_blocks: Vec::new(), + deposits: HashMap::new(), + system_config, + system_config_update: (l1_start_block, None), + } + } + + async fn try_ingest_block(&mut self) -> Result<()> { + if self.current_block > self.finalized_block { + let finalized_block = self.get_finalized().await?; + + // Only update finalized block if it has changed to avoid spamming the channel. + if self.finalized_block < finalized_block { + tracing::debug!("[l1] finalized block updated to {}", finalized_block); + self.finalized_block = finalized_block; + self.block_update_sender + .send(BlockUpdate::FinalityUpdate(finalized_block)) + .await?; + + self.unfinalized_blocks + .retain(|b| b.number > self.finalized_block) + } + } + + if self.current_block > self.head_block { + let head_block = self.get_head().await?; + self.head_block = head_block; + } + + if self.current_block <= self.head_block { + self.update_system_config().await?; + + let block = self.get_block(self.current_block).await?; + let user_deposits = self.get_deposits(self.current_block).await?; + let finalized = self.current_block >= self.finalized_block; + + let l1_info = L1Info::new( + &block, + user_deposits, + self.config.chain.batch_inbox, + finalized, + self.system_config, + )?; + + if l1_info.block_info.number >= self.finalized_block { + let block_info = BlockInfo { + hash: l1_info.block_info.hash, + number: l1_info.block_info.number, + timestamp: l1_info.block_info.timestamp, + parent_hash: block.parent_hash, + }; + + self.unfinalized_blocks.push(block_info); + } + + let update = if self.check_reorg() { + BlockUpdate::Reorg + } else { + BlockUpdate::NewBlock(Box::new(l1_info)) + }; + + self.block_update_sender.send(update).await?; + + self.current_block += 1; + } else { + sleep(Duration::from_millis(250)).await; + } + + Ok(()) + } + + async fn update_system_config(&mut self) -> Result<()> { + let (last_update_block, _) = self.system_config_update; + + if last_update_block < self.current_block { + let to_block = last_update_block + 1000; + let filter = Filter::new() + .address(self.config.chain.system_config_contract) + .topic0(*CONFIG_UPDATE_TOPIC) + .from_block(last_update_block + 1) + .to_block(to_block); + + let updates = self.provider.get_logs(&filter).await?; + let update = updates.into_iter().next(); + + let update_block = update.as_ref().and_then(|update| update.block_number); + let update = update.and_then(|update| SystemConfigUpdate::try_from(update).ok()); + + if let Some((update_block, update)) = update_block.zip(update) { + let mut config = self.system_config; + match update { + SystemConfigUpdate::BatchSender(addr) => { + config.batch_sender = addr; + } + SystemConfigUpdate::Fees(overhead, scalar) => { + config.l1_fee_overhead = overhead; + config.l1_fee_scalar = scalar; + } + SystemConfigUpdate::Gas(gas) => { + config.gas_limit = gas; + } + SystemConfigUpdate::UnsafeBlockSigner(addr) => { + config.unsafe_block_signer = addr; + } + } + + self.system_config_update = (update_block.as_u64(), Some(config)); + } else { + self.system_config_update = (to_block, None); + } + } + + let (last_update_block, next_config) = self.system_config_update; + + if last_update_block == self.current_block { + if let Some(next_config) = next_config { + tracing::info!("system config updated"); + tracing::debug!("{:?}", next_config); + self.system_config = next_config; + } + } + + Ok(()) + } + + fn check_reorg(&self) -> bool { + let len = self.unfinalized_blocks.len(); + if len >= 2 { + let last = self.unfinalized_blocks[len - 1]; + let parent = self.unfinalized_blocks[len - 2]; + last.parent_hash != parent.hash + } else { + false + } + } + + async fn get_finalized(&self) -> Result { + let block_number = match self.config.devnet { + false => BlockNumber::Finalized, + true => BlockNumber::Latest, + }; + + Ok(self + .provider + .get_block(block_number) + .await? + .ok_or(eyre::eyre!("block not found"))? + .number + .ok_or(eyre::eyre!("block pending"))? + .as_u64()) + } + + async fn get_head(&self) -> Result { + Ok(self + .provider + .get_block(BlockNumber::Latest) + .await? + .ok_or(eyre::eyre!("block not found"))? + .number + .ok_or(eyre::eyre!("block pending"))? + .as_u64()) + } + + async fn get_block(&self, block_num: u64) -> Result> { + self.provider + .get_block_with_txs(block_num) + .await? + .ok_or(eyre::eyre!("block not found")) + } + + async fn get_deposits(&mut self, block_num: u64) -> Result> { + match self.deposits.remove(&block_num) { + Some(deposits) => Ok(deposits), + None => { + let end_block = self.head_block.min(block_num + 1000); + + let deposit_filter = Filter::new() + .address(self.config.chain.deposit_contract) + .topic0(*TRANSACTION_DEPOSITED_TOPIC) + .from_block(block_num) + .to_block(end_block); + + let deposit_logs = self + .provider + .get_logs(&deposit_filter) + .await? + .into_iter() + .map(|log| UserDeposited::try_from(log).unwrap()) + .collect::>(); + + for num in block_num..=end_block { + let deposits = deposit_logs + .iter() + .filter(|d| d.l1_block_num == num) + .cloned() + .collect(); + + self.deposits.insert(num, deposits); + } + + Ok(self.deposits.remove(&block_num).unwrap()) + } + } + } +} + +fn generate_http_provider(url: &str) -> Arc>> { + let client = reqwest::ClientBuilder::new() + .timeout(Duration::from_secs(5)) + .build() + .unwrap(); + let http = Http::new_with_client(Url::parse(url).expect("ivnalid rpc url"), client); + let policy = Box::new(HttpRateLimitRetryPolicy); + let client = RetryClient::new(http, policy, 100, 50); + Arc::new(Provider::new(client)) +} + +fn start_watcher( + l1_start_block: u64, + l2_start_block: u64, + config: Arc, +) -> Result<(JoinHandle<()>, mpsc::Receiver)> { + let (block_update_sender, block_update_receiver) = mpsc::channel(1000); + + let handle = spawn(async move { + let mut watcher = + InnerWatcher::new(config, block_update_sender, l1_start_block, l2_start_block).await; + + loop { + tracing::debug!("fetching L1 data for block {}", watcher.current_block); + if let Err(err) = watcher.try_ingest_block().await { + tracing::warn!( + "failed to fetch data for block {}: {}", + watcher.current_block, + err + ); + } + } + }); + + Ok((handle, block_update_receiver)) +} diff --git a/src/l1/config_updates.rs b/src/l1/config_updates.rs new file mode 100644 index 00000000..54940b0b --- /dev/null +++ b/src/l1/config_updates.rs @@ -0,0 +1,78 @@ +use ethers::types::{Address, Log, U256}; +use eyre::Result; + +pub enum SystemConfigUpdate { + BatchSender(Address), + Fees(U256, U256), + Gas(U256), + UnsafeBlockSigner(Address), +} + +impl TryFrom for SystemConfigUpdate { + type Error = eyre::Report; + + fn try_from(log: Log) -> Result { + let version = log + .topics + .get(1) + .ok_or(eyre::eyre!("invalid system config update"))? + .to_low_u64_be(); + + if version != 0 { + return Err(eyre::eyre!("invalid system config update")); + } + + let update_type = log + .topics + .get(2) + .ok_or(eyre::eyre!("invalid system config update"))? + .to_low_u64_be(); + + match update_type { + 0 => { + let addr_bytes = log + .data + .get(76..96) + .ok_or(eyre::eyre!("invalid system config update"))?; + + let addr = Address::from_slice(addr_bytes); + Ok(Self::BatchSender(addr)) + } + 1 => { + let fee_overhead = log + .data + .get(64..96) + .ok_or(eyre::eyre!("invalid system config update"))?; + + let fee_scalar = log + .data + .get(96..128) + .ok_or(eyre::eyre!("invalid system config update"))?; + + let fee_overhead = U256::from_big_endian(fee_overhead); + let fee_scalar = U256::from_big_endian(fee_scalar); + + Ok(Self::Fees(fee_overhead, fee_scalar)) + } + 2 => { + let gas_bytes = log + .data + .get(64..96) + .ok_or(eyre::eyre!("invalid system config update"))?; + + let gas = U256::from_big_endian(gas_bytes); + Ok(Self::Gas(gas)) + } + 3 => { + let addr_bytes = log + .data + .get(76..96) + .ok_or(eyre::eyre!("invalid system config update"))?; + + let addr = Address::from_slice(addr_bytes); + Ok(Self::UnsafeBlockSigner(addr)) + } + _ => Err(eyre::eyre!("invalid system config update")), + } + } +} diff --git a/src/l1/l1_info.rs b/src/l1/l1_info.rs new file mode 100644 index 00000000..ea0c500b --- /dev/null +++ b/src/l1/l1_info.rs @@ -0,0 +1,87 @@ +use ethers::types::{Address, Block, Transaction, H256, U256}; +use eyre::Result; + +use crate::{config::SystemConfig, derive::stages::attributes::UserDeposited}; + +type BatcherTransactionData = Vec; + +/// Data tied to a specific L1 block +#[derive(Debug)] +pub struct L1Info { + /// L1 block data + pub block_info: L1BlockInfo, + /// The system config at the block + pub system_config: SystemConfig, + /// User deposits from that block + pub user_deposits: Vec, + /// Batcher transactions in block + pub batcher_transactions: Vec, + /// Whether the block has finalized + pub finalized: bool, +} + +/// L1 block info +#[derive(Debug, Clone)] +pub struct L1BlockInfo { + /// L1 block number + pub number: u64, + /// L1 block hash + pub hash: H256, + /// L1 block timestamp + pub timestamp: u64, + /// L1 base fee per gas + pub base_fee: U256, + /// L1 mix hash (prevrandao) + pub mix_hash: H256, +} + +impl L1Info { + pub fn new( + block: &Block, + user_deposits: Vec, + batch_inbox: Address, + finalized: bool, + system_config: SystemConfig, + ) -> Result { + let block_number = block + .number + .ok_or(eyre::eyre!("block not included"))? + .as_u64(); + + let block_hash = block.hash.ok_or(eyre::eyre!("block not included"))?; + + let block_info = L1BlockInfo { + number: block_number, + hash: block_hash, + timestamp: block.timestamp.as_u64(), + base_fee: block + .base_fee_per_gas + .ok_or(eyre::eyre!("block is pre london"))?, + mix_hash: block.mix_hash.ok_or(eyre::eyre!("block not included"))?, + }; + + let batcher_transactions = + create_batcher_transactions(block, system_config.batch_sender, batch_inbox); + + Ok(L1Info { + block_info, + system_config, + user_deposits, + batcher_transactions, + finalized, + }) + } +} + +fn create_batcher_transactions( + block: &Block, + batch_sender: Address, + batch_inbox: Address, +) -> Vec { + block + .transactions + .iter() + .filter(|tx| tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false)) + .map(|tx| tx.input.to_vec()) + .collect() +} diff --git a/src/l1/mod.rs b/src/l1/mod.rs index 40626500..c81df75b 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -1,642 +1,8 @@ -use std::{collections::HashMap, sync::Arc, time::Duration}; +pub mod chain_watcher; +pub use chain_watcher::{BlockUpdate, ChainWatcher}; -use ethers::{ - providers::{Http, HttpRateLimitRetryPolicy, Middleware, Provider, RetryClient}, - types::Log, -}; -use ethers::{ - types::{Address, Block, BlockNumber, Filter, Transaction, H256, U256}, - utils::keccak256, -}; +pub mod config_updates; +pub use config_updates::SystemConfigUpdate; -use eyre::Result; -use once_cell::sync::Lazy; -use reqwest::Url; -use tokio::{spawn, sync::mpsc, task::JoinHandle, time::sleep}; - -use crate::{ - common::BlockInfo, - config::{Config, SystemConfig}, - derive::stages::attributes::UserDeposited, -}; - -/// [H256] event signature for `ConfigUpdate`. -static CONFIG_UPDATE_TOPIC: Lazy = - Lazy::new(|| H256::from_slice(&keccak256("ConfigUpdate(uint256,uint8,bytes)"))); - -/// [H256] event signature for `TransactionDeposited`. -static TRANSACTION_DEPOSITED_TOPIC: Lazy = Lazy::new(|| { - H256::from_slice(&keccak256( - "TransactionDeposited(address,address,uint256,bytes)", - )) -}); - -/// Handles watching the L1 chain and monitoring for new blocks, deposits, -/// and batcher transactions. The monitoring loop is spawned in a separate -/// task and communication happens via the internal channels. When ChainWatcher -/// is dropped, the monitoring task is automatically aborted. -pub struct ChainWatcher { - /// Task handle for the monitoring loop - handle: Option>, - /// Global config - config: Arc, - /// The L1 starting block - l1_start_block: u64, - /// The L2 starting block - l2_start_block: u64, - /// Channel for receiving block updates for each new block - block_update_receiver: Option>, -} - -/// Updates L1Info -pub enum BlockUpdate { - /// A new block extending the current chain - NewBlock(Box), - /// Updates the most recent finalized block - FinalityUpdate(u64), - /// Reorg detected - Reorg, -} - -/// Data tied to a specific L1 block -#[derive(Debug)] -pub struct L1Info { - /// L1 block data - pub block_info: L1BlockInfo, - /// The system config at the block - pub system_config: SystemConfig, - /// User deposits from that block - pub user_deposits: Vec, - /// Batcher transactions in block - pub batcher_transactions: Vec, - /// Whether the block has finalized - pub finalized: bool, -} - -/// L1 block info -#[derive(Debug, Clone)] -pub struct L1BlockInfo { - /// L1 block number - pub number: u64, - /// L1 block hash - pub hash: H256, - /// L1 block timestamp - pub timestamp: u64, - /// L1 base fee per gas - pub base_fee: U256, - /// L1 mix hash (prevrandao) - pub mix_hash: H256, -} - -/// Watcher actually ingests the L1 blocks. Should be run in another -/// thread and called periodically to keep updating channels -struct InnerWatcher { - /// Global Config - config: Arc, - /// Ethers provider for L1 - provider: Arc>>, - /// Channel to send block updates - block_update_sender: mpsc::Sender, - /// The current L1 block to process - current_block: u64, - /// Most recent L1 block - head_block: u64, - /// Most recent finalized L1 block - finalized_block: u64, - /// List of L1 blocks that have not been finalized yet - unfinalized_blocks: Vec, - /// Mapping from block number to user deposits. Past block deposits - /// are removed as they are no longer needed - deposits: HashMap>, - /// Current system config value - system_config: SystemConfig, - /// Next system config if it exists and the L1 block number it activates - system_config_update: (u64, Option), -} - -/// A type alias for a vector of bytes. Represents the calldata in a batcher transaction -type BatcherTransactionData = Vec; - -impl Drop for ChainWatcher { - fn drop(&mut self) { - if let Some(handle) = self.handle.take() { - handle.abort(); - } - } -} - -impl ChainWatcher { - /// Creates a new [ChainWatcher] - pub fn new(l1_start_block: u64, l2_start_block: u64, config: Arc) -> Result { - Ok(Self { - handle: None, - config, - l1_start_block, - l2_start_block, - block_update_receiver: None, - }) - } - - /// Starts the chain watcher at the current [ChainWatcher] start blocks - pub fn start(&mut self) -> Result<()> { - if let Some(handle) = self.handle.take() { - handle.abort(); - } - - let (handle, recv) = start_watcher( - self.l1_start_block, - self.l2_start_block, - self.config.clone(), - )?; - - self.handle = Some(handle); - self.block_update_receiver = Some(recv); - - Ok(()) - } - - /// Resets the chain watcher at the given block numbers - pub fn restart(&mut self, l1_start_block: u64, l2_start_block: u64) -> Result<()> { - if let Some(handle) = self.handle.take() { - handle.abort(); - } - - let (handle, recv) = start_watcher(l1_start_block, l2_start_block, self.config.clone())?; - - self.handle = Some(handle); - self.block_update_receiver = Some(recv); - self.l1_start_block = l1_start_block; - self.l2_start_block = l2_start_block; - - Ok(()) - } - - /// Attempts to receive a message from the block update channel. - /// Returns an error if the channel contains no messages. - pub fn try_recv_from_channel(&mut self) -> Result { - let receiver = self - .block_update_receiver - .as_mut() - .ok_or(eyre::eyre!("the watcher hasn't started"))?; - - receiver.try_recv().map_err(eyre::Report::from) - } - - /// Asynchronously receives from the block update channel. - /// Returns `None` if the channel contains no messages. - pub async fn recv_from_channel(&mut self) -> Option { - match &mut self.block_update_receiver { - Some(receiver) => receiver.recv().await, - None => None, - } - } -} - -impl InnerWatcher { - /// Creates a new [InnerWatcher] - async fn new( - config: Arc, - block_update_sender: mpsc::Sender, - l1_start_block: u64, - l2_start_block: u64, - ) -> Self { - let provider = generate_http_provider(&config.l1_rpc_url); - - let system_config = if l2_start_block == config.chain.l2_genesis.number { - config.chain.system_config - } else { - let l2_provider = generate_http_provider(&config.l2_rpc_url); - - let block = l2_provider - .get_block_with_txs(l2_start_block - 1) - .await - .unwrap() - .unwrap(); - - let input = &block - .transactions - .first() - .expect( - "Could not find the L1 attributes deposited transaction in the parent L2 block", - ) - .input; - - let batch_sender = Address::from_slice(&input[176..196]); - let l1_fee_overhead = U256::from(H256::from_slice(&input[196..228]).as_bytes()); - let l1_fee_scalar = U256::from(H256::from_slice(&input[228..260]).as_bytes()); - - SystemConfig { - batch_sender, - l1_fee_overhead, - l1_fee_scalar, - gas_limit: block.gas_limit, - // TODO: fetch from contract - unsafe_block_signer: config.chain.system_config.unsafe_block_signer, - } - }; - - Self { - config, - provider, - block_update_sender, - current_block: l1_start_block, - head_block: 0, - finalized_block: 0, - unfinalized_blocks: Vec::new(), - deposits: HashMap::new(), - system_config, - system_config_update: (l1_start_block, None), - } - } - - /// Handles processing of the next L1 block. - /// - /// - Updates the finalized L1 block if this has changed and notifies the block update channel. - /// - Updates the L1 head block. - /// - Checks for system config changes and updates the [SystemConfig] in [InnerWatcher] if necessary. - /// - Fetches the block + user deposited transactions - /// - Notifies the block update channel that either a new block, or a reorg was received. - async fn try_ingest_block(&mut self) -> Result<()> { - if self.current_block > self.finalized_block { - let finalized_block = self.get_finalized().await?; - - // Only update finalized block if it has changed to avoid spamming the channel. - if self.finalized_block < finalized_block { - tracing::debug!("[l1] finalized block updated to {}", finalized_block); - self.finalized_block = finalized_block; - self.block_update_sender - .send(BlockUpdate::FinalityUpdate(finalized_block)) - .await?; - - self.unfinalized_blocks - .retain(|b| b.number > self.finalized_block) - } - } - - if self.current_block > self.head_block { - self.head_block = self.get_head().await?; - } - - if self.current_block <= self.head_block { - self.update_system_config().await?; - - let block = self.get_block(self.current_block).await?; - let user_deposits = self.get_deposits(self.current_block).await?; - let finalized = self.current_block <= self.finalized_block; - - let l1_info = L1Info::new( - &block, - user_deposits, - self.config.chain.batch_inbox, - finalized, - self.system_config, - )?; - - if l1_info.block_info.number >= self.finalized_block { - let block_info = BlockInfo { - hash: l1_info.block_info.hash, - number: l1_info.block_info.number, - timestamp: l1_info.block_info.timestamp, - parent_hash: block.parent_hash, - }; - - self.unfinalized_blocks.push(block_info); - } - - let update = if self.check_reorg() { - BlockUpdate::Reorg - } else { - BlockUpdate::NewBlock(Box::new(l1_info)) - }; - - self.block_update_sender.send(update).await?; - - self.current_block += 1; - } else { - sleep(Duration::from_millis(250)).await; - } - - Ok(()) - } - - /// Checks L1 event logs for emitted `ConfigUpdated` events and updates the [SystemConfig] in the [InnerWatcher] - async fn update_system_config(&mut self) -> Result<()> { - let (last_update_block, _) = self.system_config_update; - - if last_update_block < self.current_block { - let to_block = last_update_block + 1000; - let filter = Filter::new() - .address(self.config.chain.system_config_contract) - .topic0(*CONFIG_UPDATE_TOPIC) - .from_block(last_update_block + 1) - .to_block(to_block); - - let updates = self.provider.get_logs(&filter).await?; - let update = updates.into_iter().next(); - - let update_block = update.as_ref().and_then(|update| update.block_number); - let update = update.and_then(|update| SystemConfigUpdate::try_from(update).ok()); - - if let Some((update_block, update)) = update_block.zip(update) { - let mut config = self.system_config; - match update { - SystemConfigUpdate::BatchSender(addr) => { - config.batch_sender = addr; - } - SystemConfigUpdate::Fees(overhead, scalar) => { - config.l1_fee_overhead = overhead; - config.l1_fee_scalar = scalar; - } - SystemConfigUpdate::Gas(gas) => { - config.gas_limit = gas; - } - SystemConfigUpdate::UnsafeBlockSigner(addr) => { - config.unsafe_block_signer = addr; - } - } - - self.system_config_update = (update_block.as_u64(), Some(config)); - } else { - self.system_config_update = (to_block, None); - } - } - - let (last_update_block, next_config) = self.system_config_update; - - if last_update_block == self.current_block { - if let Some(next_config) = next_config { - tracing::info!("system config updated"); - tracing::debug!("{:?}", next_config); - self.system_config = next_config; - } - } - - Ok(()) - } - - /// True if there are 2 or more unfinalized blocks, and the parent hash - /// of the last unfinalized block is not the hash of the second last unfinalized block - fn check_reorg(&self) -> bool { - let len = self.unfinalized_blocks.len(); - if len >= 2 { - let last = self.unfinalized_blocks[len - 1]; - let parent = self.unfinalized_blocks[len - 2]; - last.parent_hash != parent.hash - } else { - false - } - } - - /// Fetches the most recent finalized L1 block number. - /// If running in devnet mode this will fetch the latest block number. - async fn get_finalized(&self) -> Result { - let block_number = match self.config.devnet { - false => BlockNumber::Finalized, - true => BlockNumber::Latest, - }; - - Ok(self - .provider - .get_block(block_number) - .await? - .ok_or(eyre::eyre!("block not found"))? - .number - .ok_or(eyre::eyre!("block pending"))? - .as_u64()) - } - - /// Fetches the most recent L1 block number - async fn get_head(&self) -> Result { - Ok(self - .provider - .get_block(BlockNumber::Latest) - .await? - .ok_or(eyre::eyre!("block not found"))? - .number - .ok_or(eyre::eyre!("block pending"))? - .as_u64()) - } - - /// Fetches a given L1 block - async fn get_block(&self, block_num: u64) -> Result> { - self.provider - .get_block_with_txs(block_num) - .await? - .ok_or(eyre::eyre!("block not found")) - } - - /// Returns all user deposited transactions in an L1 block. - /// - /// If the [InnerWatcher] has already stored deposits in the given block, it removes and returns these. - /// - /// Otherwise `TransactionDeposited` event logs are fetched from an L1 block range - /// of `block_num` to `block_num + 1000`, and stored in the `deposits` mapping. - async fn get_deposits(&mut self, block_num: u64) -> Result> { - match self.deposits.remove(&block_num) { - Some(deposits) => Ok(deposits), - None => { - let end_block = self.head_block.min(block_num + 1000); - - let deposit_filter = Filter::new() - .address(self.config.chain.deposit_contract) - .topic0(*TRANSACTION_DEPOSITED_TOPIC) - .from_block(block_num) - .to_block(end_block); - - let deposit_logs = self - .provider - .get_logs(&deposit_filter) - .await? - .into_iter() - .map(|log| UserDeposited::try_from(log).unwrap()) - .collect::>(); - - for num in block_num..=end_block { - let deposits = deposit_logs - .iter() - .filter(|d| d.l1_block_num == num) - .cloned() - .collect(); - - self.deposits.insert(num, deposits); - } - - Ok(self.deposits.remove(&block_num).unwrap()) - } - } - } -} - -impl L1Info { - /// Creates a new [L1Info] instance. - pub fn new( - block: &Block, - user_deposits: Vec, - batch_inbox: Address, - finalized: bool, - system_config: SystemConfig, - ) -> Result { - let block_number = block - .number - .ok_or(eyre::eyre!("block not included"))? - .as_u64(); - - let block_hash = block.hash.ok_or(eyre::eyre!("block not included"))?; - - let block_info = L1BlockInfo { - number: block_number, - hash: block_hash, - timestamp: block.timestamp.as_u64(), - base_fee: block - .base_fee_per_gas - .ok_or(eyre::eyre!("block is pre london"))?, - mix_hash: block.mix_hash.ok_or(eyre::eyre!("block not included"))?, - }; - - let batcher_transactions = - create_batcher_transactions(block, system_config.batch_sender, batch_inbox); - - Ok(L1Info { - block_info, - system_config, - user_deposits, - batcher_transactions, - finalized, - }) - } -} - -/// Filters block transactions and returns calldata in transactions sent from the batch sender to the batch inbox. -fn create_batcher_transactions( - block: &Block, - batch_sender: Address, - batch_inbox: Address, -) -> Vec { - block - .transactions - .iter() - .filter(|tx| tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false)) - .map(|tx| tx.input.to_vec()) - .collect() -} - -/// Creates the block update channel and begins a loop to ingest L1 blocks via [InnerWatcher::try_ingest_block()] -fn start_watcher( - l1_start_block: u64, - l2_start_block: u64, - config: Arc, -) -> Result<(JoinHandle<()>, mpsc::Receiver)> { - let (block_update_sender, block_update_receiver) = mpsc::channel(1000); - - let handle = spawn(async move { - let mut watcher = - InnerWatcher::new(config, block_update_sender, l1_start_block, l2_start_block).await; - - loop { - tracing::debug!("fetching L1 data for block {}", watcher.current_block); - if let Err(err) = watcher.try_ingest_block().await { - tracing::warn!( - "failed to fetch data for block {}: {}", - watcher.current_block, - err - ); - } - } - }); - - Ok((handle, block_update_receiver)) -} - -/// Represents which config option has been updated. -enum SystemConfigUpdate { - /// An update of the batcher address - BatchSender(Address), - /// An update of the fee scalar and/or overhead - Fees(U256, U256), - /// A update of the L2 block gas limit - Gas(U256), - /// An update of the unsafe block signer - UnsafeBlockSigner(Address), -} - -impl TryFrom for SystemConfigUpdate { - type Error = eyre::Report; - - /// Parses the updated config value from an event [Log] and return a [SystemConfigUpdate] - fn try_from(log: Log) -> Result { - let version = log - .topics - .get(1) - .ok_or(eyre::eyre!("invalid system config update"))? - .to_low_u64_be(); - - if version != 0 { - return Err(eyre::eyre!("invalid system config update")); - } - - let update_type = log - .topics - .get(2) - .ok_or(eyre::eyre!("invalid system config update"))? - .to_low_u64_be(); - - match update_type { - 0 => { - let addr_bytes = log - .data - .get(76..96) - .ok_or(eyre::eyre!("invalid system config update"))?; - - let addr = Address::from_slice(addr_bytes); - Ok(Self::BatchSender(addr)) - } - 1 => { - let fee_overhead = log - .data - .get(64..96) - .ok_or(eyre::eyre!("invalid system config update"))?; - - let fee_scalar = log - .data - .get(96..128) - .ok_or(eyre::eyre!("invalid system config update"))?; - - let fee_overhead = U256::from_big_endian(fee_overhead); - let fee_scalar = U256::from_big_endian(fee_scalar); - - Ok(Self::Fees(fee_overhead, fee_scalar)) - } - 2 => { - let gas_bytes = log - .data - .get(64..96) - .ok_or(eyre::eyre!("invalid system config update"))?; - - let gas = U256::from_big_endian(gas_bytes); - Ok(Self::Gas(gas)) - } - 3 => { - let addr_bytes = log - .data - .get(76..96) - .ok_or(eyre::eyre!("invalid system config update"))?; - - let addr = Address::from_slice(addr_bytes); - Ok(Self::UnsafeBlockSigner(addr)) - } - _ => Err(eyre::eyre!("invalid system config update")), - } - } -} - -/// Creates a retryable ethers RPC [Provider] -fn generate_http_provider(url: &str) -> Arc>> { - let client = reqwest::ClientBuilder::new() - .timeout(Duration::from_secs(5)) - .build() - .unwrap(); - let http = Http::new_with_client(Url::parse(url).expect("invalid rpc url"), client); - let policy = Box::new(HttpRateLimitRetryPolicy); - let client = RetryClient::new(http, policy, 100, 50); - Arc::new(Provider::new(client)) -} +pub mod l1_info; +pub use l1_info::L1Info; From eb9b0378d7e82af526023b380650a9ffebff0076 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 28 Jan 2024 17:23:11 +0100 Subject: [PATCH 02/23] feat: added L1 beacon api connection --- bin/magi.rs | 3 ++ docker/.env.default | 4 +++ docker/start-magi.sh | 2 ++ docs/architecture.md | 1 + src/config/mod.rs | 4 +++ src/derive/mod.rs | 1 + src/derive/stages/channels.rs | 1 + src/driver/info.rs | 1 + src/driver/mod.rs | 1 + src/l1/beacon_api.rs | 61 +++++++++++++++++++++++++++++++++++ src/l1/chain_watcher.rs | 2 +- src/l1/mod.rs | 3 ++ 12 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/l1/beacon_api.rs diff --git a/bin/magi.rs b/bin/magi.rs index 6d523dfd..dab1b9de 100644 --- a/bin/magi.rs +++ b/bin/magi.rs @@ -44,6 +44,8 @@ pub struct Cli { #[clap(long)] l1_rpc_url: Option, #[clap(long)] + l1_beacon_url: Option, + #[clap(long)] l2_rpc_url: Option, #[clap(short = 'm', long, default_value = "full")] sync_mode: SyncMode, @@ -109,6 +111,7 @@ impl From for CliConfig { let jwt_secret = value.jwt_secret(); Self { l1_rpc_url: value.l1_rpc_url, + l1_beacon_url: value.l1_beacon_url, l2_rpc_url: value.l2_rpc_url, l2_engine_url: value.l2_engine_url, jwt_secret, diff --git a/docker/.env.default b/docker/.env.default index 4929562c..70769df3 100644 --- a/docker/.env.default +++ b/docker/.env.default @@ -5,6 +5,10 @@ NETWORK=optimism # The HTTP RPC endpoint of an L1 node L1_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/ +# The HTTP Beacon chain RPC endpoint of an L1 node +# (this is required if using EIP-4844 DA) +L1_BEACON_RPC_URL= + # The WebSocket RPC endpoint of an L1 node L1_WS_RPC_URL=wss://eth-mainnet.g.alchemy.com/v2/ diff --git a/docker/start-magi.sh b/docker/start-magi.sh index c1b984d8..8292d0ff 100755 --- a/docker/start-magi.sh +++ b/docker/start-magi.sh @@ -18,6 +18,7 @@ then --network $NETWORK \ --jwt-secret $JWT_SECRET \ --l1-rpc-url $L1_RPC_URL \ + --l1-beacon-url $L1_BEACON_URL \ --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ @@ -30,6 +31,7 @@ then --network $NETWORK \ --jwt-secret $JWT_SECRET \ --l1-rpc-url $L1_RPC_URL \ + --l1-beacon-url $L1_BEACON_URL \ --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ diff --git a/docs/architecture.md b/docs/architecture.md index a4de9397..2ee135e3 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -93,6 +93,7 @@ The [Config](../src/config/mod.rs) object contains the system configuration for **Config** - `l1_rpc_url`: The L1 RPC endpoint to use for the L1 chain watcher. +- `l1_beacon_url`: The L1 beacon chain RPC endpoint. - `l2_rpc_url`: The L2 chain RPC endpoint - `l2_engine_url`: The L2 chain engine API URL (see [Engine API](#engine-api)). - `chain`: A `ChainConfig` object detailed below. diff --git a/src/config/mod.rs b/src/config/mod.rs index 5bcfd89a..5ba1b5eb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -41,6 +41,8 @@ impl FromStr for SyncMode { pub struct Config { /// The L1 chain RPC URL pub l1_rpc_url: String, + /// The base chain beacon client RPC URL + pub l1_beacon_url: String, /// The L2 chain RPC URL pub l2_rpc_url: String, /// The L2 engine API URL @@ -105,6 +107,8 @@ pub struct CliConfig { pub l1_rpc_url: Option, /// The L2 execution client RPC #[serde(skip_serializing_if = "Option::is_none")] + pub l1_beacon_url: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub l2_rpc_url: Option, /// The L2 engine RPC #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/derive/mod.rs b/src/derive/mod.rs index 3bc11be8..b09e13ee 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -116,6 +116,7 @@ mod tests { 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(), diff --git a/src/derive/stages/channels.rs b/src/derive/stages/channels.rs index 923e27a0..6492e37e 100644 --- a/src/derive/stages/channels.rs +++ b/src/derive/stages/channels.rs @@ -406,6 +406,7 @@ mod tests { ) { let config = Config { l1_rpc_url: String::new(), + l1_beacon_url: String::new(), l2_rpc_url: String::new(), l2_engine_url: String::new(), jwt_secret: String::new(), diff --git a/src/driver/info.rs b/src/driver/info.rs index 5577808c..73e5b873 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -134,6 +134,7 @@ mod test_utils { pub fn optimism_config() -> Config { Config { l1_rpc_url: Default::default(), + l1_beacon_url: Default::default(), l2_rpc_url: Default::default(), l2_engine_url: Default::default(), chain: ChainConfig::optimism(), diff --git a/src/driver/mod.rs b/src/driver/mod.rs index e8ff1252..aedab6eb 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -385,6 +385,7 @@ mod tests { 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( diff --git a/src/l1/beacon_api.rs b/src/l1/beacon_api.rs new file mode 100644 index 00000000..6500dce4 --- /dev/null +++ b/src/l1/beacon_api.rs @@ -0,0 +1,61 @@ +use eyre::Result; +use serde_json::Value; + +pub struct L1BeaconApi { + l1_beacon_url: String, + client: reqwest::Client, +} + +pub enum BlobFilter { + Slot(u64), + BlockRoot(String), + Head, + Genesis, + Finalized, +} + +impl L1BeaconApi { + pub fn new(l1_beacon_url: String) -> Self { + Self { + l1_beacon_url, + client: reqwest::Client::new(), + } + } + + /// Get all blobs for a specific slot + pub async fn get_blob_sidecars(&self, filter: BlobFilter) -> Result { + let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.l1_beacon_url); + let full_url = match filter { + BlobFilter::Head => format!("{}/head", base_url), + BlobFilter::Genesis => format!("{}/genesis", base_url), + BlobFilter::Finalized => format!("{}/finalized", base_url), + BlobFilter::BlockRoot(block_root) => format!("{}/{}", base_url, block_root), + BlobFilter::Slot(slot) => format!("{}/{}", base_url, slot), + }; + + let resp = self.client.get(full_url).send().await?.error_for_status()?; + + let body = resp.text().await?; + let blob = serde_json::from_str(&body)?; + Ok(blob) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_get_blobs() { + // TODO: use env vars in tests + // let Ok(l1_beacon_url) = std::env::var("L1_BEACON_TEST_RPC_URL") else { + // return; + // }; + let l1_beacon_url = "https://remotelab.taila355b.ts.net".to_string(); + + let retriever = L1BeaconApi::new(l1_beacon_url); + let blobs = retriever.get_blob_sidecars(BlobFilter::Head).await.unwrap(); + + println!("blobs: {:?}", blobs); + } +} diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index 902c9eed..c00de8ae 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -416,7 +416,7 @@ fn generate_http_provider(url: &str) -> Arc>> { .timeout(Duration::from_secs(5)) .build() .unwrap(); - let http = Http::new_with_client(Url::parse(url).expect("ivnalid rpc url"), client); + let http = Http::new_with_client(Url::parse(url).expect("invalid rpc url"), client); let policy = Box::new(HttpRateLimitRetryPolicy); let client = RetryClient::new(http, policy, 100, 50); Arc::new(Provider::new(client)) diff --git a/src/l1/mod.rs b/src/l1/mod.rs index c81df75b..f062ae32 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -6,3 +6,6 @@ pub use config_updates::SystemConfigUpdate; pub mod l1_info; pub use l1_info::L1Info; + +pub mod beacon_api; +pub use beacon_api::{BlobFilter, L1BeaconApi}; From 8f0f41f4601154f4979ec006dad5709d8d025583 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 2 Feb 2024 20:56:16 +0100 Subject: [PATCH 03/23] feat: blob fetcher --- src/derive/mod.rs | 9 +-- src/driver/mod.rs | 7 ++- src/l1/beacon_api.rs | 61 -------------------- src/l1/blob_fetcher.rs | 122 ++++++++++++++++++++++++++++++++++++++++ src/l1/chain_watcher.rs | 23 ++++++-- src/l1/l1_info.rs | 64 +++++++-------------- src/l1/mod.rs | 4 +- 7 files changed, 171 insertions(+), 119 deletions(-) delete mode 100644 src/l1/beacon_api.rs create mode 100644 src/l1/blob_fetcher.rs diff --git a/src/derive/mod.rs b/src/derive/mod.rs index b09e13ee..419d0c52 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -157,11 +157,12 @@ mod tests { _ => panic!("wrong update type"), }; + // let calldata = l1_info.batcher_transactions.into(); + // TODO: get calldata from blob + let calldata = vec![]; + pipeline - .push_batcher_transactions( - l1_info.batcher_transactions.clone(), - l1_info.block_info.number, - ) + .push_batcher_transactions(calldata, l1_info.block_info.number) .unwrap(); state.write().unwrap().update_l1_info(l1_info); diff --git a/src/driver/mod.rs b/src/driver/mod.rs index aedab6eb..a063ff63 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -273,8 +273,11 @@ impl Driver { self.unsafe_block_signer_sender .send(l1_info.system_config.unsafe_block_signer)?; - self.pipeline - .push_batcher_transactions(l1_info.batcher_transactions.clone(), num)?; + // let calldata = l1_info.batcher_transactions.into(); + // TODO: decode valid data from blob + let calldata = vec![]; + + self.pipeline.push_batcher_transactions(calldata, num)?; self.state .write() diff --git a/src/l1/beacon_api.rs b/src/l1/beacon_api.rs deleted file mode 100644 index 6500dce4..00000000 --- a/src/l1/beacon_api.rs +++ /dev/null @@ -1,61 +0,0 @@ -use eyre::Result; -use serde_json::Value; - -pub struct L1BeaconApi { - l1_beacon_url: String, - client: reqwest::Client, -} - -pub enum BlobFilter { - Slot(u64), - BlockRoot(String), - Head, - Genesis, - Finalized, -} - -impl L1BeaconApi { - pub fn new(l1_beacon_url: String) -> Self { - Self { - l1_beacon_url, - client: reqwest::Client::new(), - } - } - - /// Get all blobs for a specific slot - pub async fn get_blob_sidecars(&self, filter: BlobFilter) -> Result { - let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.l1_beacon_url); - let full_url = match filter { - BlobFilter::Head => format!("{}/head", base_url), - BlobFilter::Genesis => format!("{}/genesis", base_url), - BlobFilter::Finalized => format!("{}/finalized", base_url), - BlobFilter::BlockRoot(block_root) => format!("{}/{}", base_url, block_root), - BlobFilter::Slot(slot) => format!("{}/{}", base_url, slot), - }; - - let resp = self.client.get(full_url).send().await?.error_for_status()?; - - let body = resp.text().await?; - let blob = serde_json::from_str(&body)?; - Ok(blob) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn test_get_blobs() { - // TODO: use env vars in tests - // let Ok(l1_beacon_url) = std::env::var("L1_BEACON_TEST_RPC_URL") else { - // return; - // }; - let l1_beacon_url = "https://remotelab.taila355b.ts.net".to_string(); - - let retriever = L1BeaconApi::new(l1_beacon_url); - let blobs = retriever.get_blob_sidecars(BlobFilter::Head).await.unwrap(); - - println!("blobs: {:?}", blobs); - } -} diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs new file mode 100644 index 00000000..06732d0d --- /dev/null +++ b/src/l1/blob_fetcher.rs @@ -0,0 +1,122 @@ +use bytes::Bytes; +use ethers::types::{Address, Block, Transaction}; +use eyre::Result; +use serde::Deserialize; +use serde_json::Value; + +const BLOB_CARRYING_TRANSACTION_TYPE: u64 = 3; + +#[derive(Debug)] +pub enum BatcherTransactionData { + Calldata(Vec), + Blob(BlobSidecar), +} + +pub struct BlobFetcher { + l1_beacon_url: String, + client: reqwest::Client, + + batch_sender: Address, + batch_inbox: Address, +} + +pub enum FetchBlobFilter { + Slot(u64), + BlockRoot(String), +} + +#[derive(Debug, Deserialize)] +pub struct BlobSidecar { + pub index: String, + pub blob: Bytes, + // kzg_commitment: String, + // kzg_proof: String, + // signed_block_header: Value, + // kzg_commitment_inclusion_proof: Vec, +} + +impl BlobFetcher { + pub fn new(l1_beacon_url: String, batch_inbox: Address, batch_sender: Address) -> Self { + Self { + l1_beacon_url, + batch_inbox, + batch_sender, + client: reqwest::Client::new(), + } + } + + pub async fn fetch_blob_sidecars(&self, filter: FetchBlobFilter) -> Result> { + let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.l1_beacon_url); + let full_url = match filter { + FetchBlobFilter::BlockRoot(block_root) => format!("{}/{}", base_url, block_root), + FetchBlobFilter::Slot(slot) => format!("{}/{}", base_url, slot), + }; + + let resp = self.client.get(full_url).send().await?.error_for_status()?; + let resp = serde_json::from_slice::(&resp.bytes().await?)?; + let resp = resp.get("data").ok_or(eyre::eyre!("No data in response"))?; + + let blobs = serde_json::from_value::>(resp.clone())?; + + Ok(blobs) + } + + pub async fn get_batcher_transactions( + &self, + block: &Block, + ) -> Result> { + let mut batcher_transactions = Vec::new(); + let mut blob_index = 0; + + for tx in block.transactions.iter() { + if !self.is_valid_batcher_transaction(tx) { + blob_index += 1; + continue; + } + + // sanity check: transactions here should always have a transaction type + let Some(tx_type) = tx.transaction_type.map(|t| t.as_u64()) else { + tracing::error!("found batcher tx without tx_type. This shouldn't happen."); + continue; + }; + + if tx_type != BLOB_CARRYING_TRANSACTION_TYPE { + batcher_transactions.push(BatcherTransactionData::Calldata(tx.input.to_vec())); + continue; + } + + // TODO: + // download blobs from the beacon chain here... + // let slot = get_slot_from_block_number(block.number); + // let blobs = self.fetch_blob_sidecars(FetchBlobFilter::Slot(slot)).await?; + } + + Ok(vec![]) + } + + fn is_valid_batcher_transaction(&self, tx: &Transaction) -> bool { + tx.from == self.batch_sender && tx.to.map(|to| to == self.batch_inbox).unwrap_or(false) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + // TODO: update with a test from mainnet after dencun is active + async fn test_get_blobs() { + // TODO: use env vars in tests + // let Ok(l1_beacon_url) = std::env::var("L1_BEACON_TEST_RPC_URL") else { + // return; + // }; + let l1_beacon_url = "https://remotelab.taila355b.ts.net".to_string(); + let retriever = BlobFetcher::new(l1_beacon_url, Address::zero(), Address::zero()); + let blobs = retriever + .fetch_blob_sidecars(FetchBlobFilter::Slot(4248703)) + .await + .unwrap(); + + assert_eq!(blobs.len(), 3); + } +} diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index c00de8ae..e18347cc 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -16,7 +16,7 @@ use crate::{ derive::stages::attributes::UserDeposited, }; -use super::{L1Info, SystemConfigUpdate}; +use super::{l1_info::L1BlockInfo, BlobFetcher, L1Info, SystemConfigUpdate}; static CONFIG_UPDATE_TOPIC: Lazy = Lazy::new(|| H256::from_slice(&keccak256("ConfigUpdate(uint256,uint8,bytes)"))); @@ -61,6 +61,8 @@ struct InnerWatcher { config: Arc, /// Ethers provider for L1 provider: Arc>>, + /// L1 beacon node to fetch blobs + blob_fetcher: Arc, /// Channel to send block updates block_update_sender: mpsc::Sender, /// Most recent ingested block @@ -165,6 +167,12 @@ impl InnerWatcher { ) -> Self { let provider = generate_http_provider(&config.l1_rpc_url); + let blob_fetcher = Arc::new(BlobFetcher::new( + config.l1_beacon_url.clone(), + config.chain.batch_inbox, + config.chain.system_config.batch_sender, + )); + let system_config = if l2_start_block == config.chain.l2_genesis.number { config.chain.system_config } else { @@ -201,6 +209,7 @@ impl InnerWatcher { Self { config, provider, + blob_fetcher, block_update_sender, current_block: l1_start_block, head_block: 0, @@ -241,13 +250,15 @@ impl InnerWatcher { let user_deposits = self.get_deposits(self.current_block).await?; let finalized = self.current_block >= self.finalized_block; - let l1_info = L1Info::new( - &block, + let batcher_transactions = self.blob_fetcher.get_batcher_transactions(&block).await?; + + let l1_info = L1Info { + system_config: self.system_config, + block_info: L1BlockInfo::try_from(&block)?, + batcher_transactions, user_deposits, - self.config.chain.batch_inbox, finalized, - self.system_config, - )?; + }; if l1_info.block_info.number >= self.finalized_block { let block_info = BlockInfo { diff --git a/src/l1/l1_info.rs b/src/l1/l1_info.rs index ea0c500b..de974f84 100644 --- a/src/l1/l1_info.rs +++ b/src/l1/l1_info.rs @@ -1,10 +1,8 @@ -use ethers::types::{Address, Block, Transaction, H256, U256}; -use eyre::Result; +use ethers::types::{Block, Transaction, H256, U256}; +use super::BatcherTransactionData; use crate::{config::SystemConfig, derive::stages::attributes::UserDeposited}; -type BatcherTransactionData = Vec; - /// Data tied to a specific L1 block #[derive(Debug)] pub struct L1Info { @@ -35,53 +33,31 @@ pub struct L1BlockInfo { pub mix_hash: H256, } -impl L1Info { - pub fn new( - block: &Block, - user_deposits: Vec, - batch_inbox: Address, - finalized: bool, - system_config: SystemConfig, - ) -> Result { - let block_number = block +impl TryFrom<&Block> for L1BlockInfo { + type Error = eyre::Error; + + fn try_from(value: &Block) -> std::result::Result { + let number = value .number .ok_or(eyre::eyre!("block not included"))? .as_u64(); - let block_hash = block.hash.ok_or(eyre::eyre!("block not included"))?; + let hash = value.hash.ok_or(eyre::eyre!("block not included"))?; + + let timestamp = value.timestamp.as_u64(); - let block_info = L1BlockInfo { - number: block_number, - hash: block_hash, - timestamp: block.timestamp.as_u64(), - base_fee: block - .base_fee_per_gas - .ok_or(eyre::eyre!("block is pre london"))?, - mix_hash: block.mix_hash.ok_or(eyre::eyre!("block not included"))?, - }; + let base_fee = value + .base_fee_per_gas + .ok_or(eyre::eyre!("block is pre london"))?; - let batcher_transactions = - create_batcher_transactions(block, system_config.batch_sender, batch_inbox); + let mix_hash = value.mix_hash.ok_or(eyre::eyre!("block not included"))?; - Ok(L1Info { - block_info, - system_config, - user_deposits, - batcher_transactions, - finalized, + Ok(L1BlockInfo { + number, + hash, + timestamp, + base_fee, + mix_hash, }) } } - -fn create_batcher_transactions( - block: &Block, - batch_sender: Address, - batch_inbox: Address, -) -> Vec { - block - .transactions - .iter() - .filter(|tx| tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false)) - .map(|tx| tx.input.to_vec()) - .collect() -} diff --git a/src/l1/mod.rs b/src/l1/mod.rs index f062ae32..09035241 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -7,5 +7,5 @@ pub use config_updates::SystemConfigUpdate; pub mod l1_info; pub use l1_info::L1Info; -pub mod beacon_api; -pub use beacon_api::{BlobFilter, L1BeaconApi}; +pub mod blob_fetcher; +pub use blob_fetcher::{BatcherTransactionData, BlobFetcher, BlobSidecar}; From a93dae7ff339014f8fd98759163e6df867a2957e Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sat, 3 Feb 2024 14:36:24 +0100 Subject: [PATCH 04/23] feat: blob decoding wip --- src/derive/mod.rs | 12 +- src/derive/stages/batcher_transactions.rs | 4 +- src/driver/mod.rs | 10 +- src/l1/blob_encoding.rs | 95 ++++++++++ src/l1/blob_fetcher.rs | 208 ++++++++++++++++------ src/l1/chain_watcher.rs | 7 +- src/l1/mod.rs | 3 + 7 files changed, 269 insertions(+), 70 deletions(-) create mode 100644 src/l1/blob_encoding.rs diff --git a/src/derive/mod.rs b/src/derive/mod.rs index 419d0c52..0180cc1c 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -1,5 +1,6 @@ use std::sync::{mpsc, Arc, RwLock}; +use bytes::Bytes; use eyre::Result; use crate::{config::Config, engine::PayloadAttributes}; @@ -64,7 +65,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<()> { self.batcher_transaction_sender .send(BatcherTransactionMessage { txs, l1_origin })?; Ok(()) @@ -157,12 +158,11 @@ mod tests { _ => panic!("wrong update type"), }; - // let calldata = l1_info.batcher_transactions.into(); - // TODO: get calldata from blob - let calldata = vec![]; - pipeline - .push_batcher_transactions(calldata, l1_info.block_info.number) + .push_batcher_transactions( + l1_info.batcher_transactions.clone(), + l1_info.block_info.number, + ) .unwrap(); state.write().unwrap().update_l1_info(l1_info); diff --git a/src/derive/stages/batcher_transactions.rs b/src/derive/stages/batcher_transactions.rs index 65c11a80..d29be466 100644 --- a/src/derive/stages/batcher_transactions.rs +++ b/src/derive/stages/batcher_transactions.rs @@ -8,7 +8,7 @@ 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 +178,7 @@ mod tests { #[test] fn test_push_tx() { - let data = hex::decode(TX_DATA).unwrap(); + let data = bytes::Bytes::from(hex::decode(TX_DATA).unwrap()); let txs = vec![data]; let (tx, rx) = mpsc::channel(); diff --git a/src/driver/mod.rs b/src/driver/mod.rs index a063ff63..cc4d3f5d 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -273,11 +273,11 @@ impl Driver { self.unsafe_block_signer_sender .send(l1_info.system_config.unsafe_block_signer)?; - // let calldata = l1_info.batcher_transactions.into(); - // TODO: decode valid data from blob - let calldata = vec![]; - - self.pipeline.push_batcher_transactions(calldata, num)?; + self.pipeline.push_batcher_transactions( + // cloning `bytes::Bytes` is cheap + l1_info.batcher_transactions.clone(), + num, + )?; self.state .write() diff --git a/src/l1/blob_encoding.rs b/src/l1/blob_encoding.rs new file mode 100644 index 00000000..6121da46 --- /dev/null +++ b/src/l1/blob_encoding.rs @@ -0,0 +1,95 @@ +use bytes::Bytes; +use eyre::Result; + +const MAX_BLOB_DATA_SIZE: usize = (4 * 31 + 3) * 1024 - 4; +const ENCODING_VERSION: u8 = 0; +const VERSION_OFFSET: usize = 0; +const ROUNDS: usize = 1024; + +pub fn decode_blob_data(blob: &Bytes) -> Result { + let mut output = vec![0; MAX_BLOB_DATA_SIZE]; + + if blob[VERSION_OFFSET] != ENCODING_VERSION { + eyre::bail!("Invalid encoding version"); + } + + // 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!("Invalid length"); + } + + output[0..27].copy_from_slice(&blob[5..32]); + + let mut output_pos = 28; + let mut input_pos = 32; + + // buffer for the 4 6-bit chunks + let mut encoded_byte = [0; 4]; + + encoded_byte[0] = blob[0]; + for byte in encoded_byte.iter_mut().skip(1) { + *byte = decode_field_element(&mut output_pos, &mut input_pos, blob, &mut output)?; + } + reassemble_bytes(&mut output_pos, encoded_byte, &mut output); + + for _ in 1..ROUNDS { + if output_pos >= output_len { + break; + } + + for byte in encoded_byte.iter_mut() { + *byte = decode_field_element(&mut output_pos, &mut input_pos, blob, &mut output)?; + } + reassemble_bytes(&mut output_pos, encoded_byte, &mut output); + } + + for output_byte in output.iter().take(MAX_BLOB_DATA_SIZE).skip(output_len) { + if output_byte != &0 { + eyre::bail!("Extraneous data in field element {}", output_pos / 32); + } + } + + output.truncate(output_len); + + for byte in blob.iter().skip(input_pos) { + if byte != &0 { + eyre::bail!("Extraneous data in input position {}", input_pos); + } + } + + Ok(output.into()) +} + +fn decode_field_element( + output_pos: &mut usize, + input_pos: &mut usize, + blob: &Bytes, + output: &mut [u8], +) -> Result { + let result = blob[*input_pos]; + + // two highest order bits of the first byte of each field element should always be 0 + if result & 0b1100_0000 != 0 { + eyre::bail!("Invalid field element"); + } + + output[*output_pos..*output_pos + 31].copy_from_slice(&blob[*input_pos + 1..*input_pos + 32]); + + *output_pos += 32; + *input_pos += 32; + + Ok(result) +} + +fn reassemble_bytes(output_pos: &mut usize, encoded_byte: [u8; 4], output: &mut [u8]) { + *output_pos -= 1; + + let x = (encoded_byte[0] & 0b0011_1111) | ((encoded_byte[1] & 0b0011_0000) << 2); + let y = (encoded_byte[1] & 0b0000_1111) | ((encoded_byte[3] & 0b0000_1111) << 4); + let z = (encoded_byte[2] & 0b0011_1111) | ((encoded_byte[3] & 0b0011_0000) << 2); + + output[*output_pos - 32] = z; + output[*output_pos - (32 * 2)] = y; + output[*output_pos - (32 * 3)] = x; +} diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index 06732d0d..ef6801d7 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -1,33 +1,38 @@ +use std::sync::{ + atomic::{AtomicU64, Ordering}, + Arc, +}; + use bytes::Bytes; -use ethers::types::{Address, Block, Transaction}; +use ethers::types::{Block, Transaction, H256}; use eyre::Result; use serde::Deserialize; use serde_json::Value; +use super::decode_blob_data; +use crate::config::Config; + const BLOB_CARRYING_TRANSACTION_TYPE: u64 = 3; -#[derive(Debug)] -pub enum BatcherTransactionData { - Calldata(Vec), - Blob(BlobSidecar), -} +pub type BatcherTransactionData = Bytes; +/// The blob fetcher is responsible for fetching blob data from the L1 beacon chain, +/// along with relevant parsing and validation. +/// +/// Consensus layer info required for deriving the slot at which a specific blob was +/// included in the beacon chain is fetched on the first call to [`Self::get_slot_from_time`] +/// and cached for all subsequent calls. pub struct BlobFetcher { - l1_beacon_url: String, + config: Arc, client: reqwest::Client, - - batch_sender: Address, - batch_inbox: Address, -} - -pub enum FetchBlobFilter { - Slot(u64), - BlockRoot(String), + genesis_timestamp: AtomicU64, + seconds_per_slot: AtomicU64, } #[derive(Debug, Deserialize)] pub struct BlobSidecar { - pub index: String, + #[serde(deserialize_with = "deserialize_string_to_u64")] + pub index: u64, pub blob: Bytes, // kzg_commitment: String, // kzg_proof: String, @@ -36,41 +41,28 @@ pub struct BlobSidecar { } impl BlobFetcher { - pub fn new(l1_beacon_url: String, batch_inbox: Address, batch_sender: Address) -> Self { + pub fn new(config: Arc) -> Self { Self { - l1_beacon_url, - batch_inbox, - batch_sender, + config, client: reqwest::Client::new(), + genesis_timestamp: AtomicU64::new(0), + seconds_per_slot: AtomicU64::new(0), } } - pub async fn fetch_blob_sidecars(&self, filter: FetchBlobFilter) -> Result> { - let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.l1_beacon_url); - let full_url = match filter { - FetchBlobFilter::BlockRoot(block_root) => format!("{}/{}", base_url, block_root), - FetchBlobFilter::Slot(slot) => format!("{}/{}", base_url, slot), - }; - - let resp = self.client.get(full_url).send().await?.error_for_status()?; - let resp = serde_json::from_slice::(&resp.bytes().await?)?; - let resp = resp.get("data").ok_or(eyre::eyre!("No data in response"))?; - - let blobs = serde_json::from_value::>(resp.clone())?; - - Ok(blobs) - } - + /// Given a block, return a list of `BatcherTransactionData` containing either the + /// calldata or the decoded blob data for each batcher transaction in the block. pub async fn get_batcher_transactions( &self, block: &Block, ) -> Result> { - let mut batcher_transactions = Vec::new(); + let mut batcher_transactions_data = Vec::new(); + let mut indexed_blobs = Vec::new(); let mut blob_index = 0; for tx in block.transactions.iter() { if !self.is_valid_batcher_transaction(tx) { - blob_index += 1; + blob_index += 1; // TODO: += number of actual tx.blob_hashes continue; } @@ -81,22 +73,134 @@ impl BlobFetcher { }; if tx_type != BLOB_CARRYING_TRANSACTION_TYPE { - batcher_transactions.push(BatcherTransactionData::Calldata(tx.input.to_vec())); + // this is necessary because ethers-rs wraps `bytes::Bytes` into its own type + // that doesn't come with free conversion back to `bytes::Bytes`. + let calldata = Bytes::from(tx.input.to_vec().clone()); + batcher_transactions_data.push(calldata); continue; } - // TODO: - // download blobs from the beacon chain here... - // let slot = get_slot_from_block_number(block.number); - // let blobs = self.fetch_blob_sidecars(FetchBlobFilter::Slot(slot)).await?; + // TODO: retrieve tx.blob_hashes. might need to update/fork ethers-rs. + // are there other ways to see how many blobs are in a tx? + let blob_hashes = vec![H256::zero()]; + for blob_hash in blob_hashes { + indexed_blobs.push((blob_index, blob_hash)); + blob_index += 1; + } + } + + // if at this point there are no blobs, return early + if indexed_blobs.is_empty() { + return Ok(batcher_transactions_data); } - Ok(vec![]) + let slot = self.get_slot_from_time(block.timestamp.as_u64()).await?; + // perf: fetch only the required indexes instead of all + let blobs = self.fetch_blob_sidecars(slot).await?; + + for (blob_index, blob_hash) in indexed_blobs { + let Some(blob_sidecar) = blobs.iter().find(|b| b.index == blob_index) 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); + }; + + // decode the full blob + let decoded_blob_data = decode_blob_data(&blob_sidecar.blob)?; + tracing::debug!("successfully decoded blob data for hash {:?}", blob_hash); + + batcher_transactions_data.push(decoded_blob_data); + } + + Ok(batcher_transactions_data) } + #[inline] fn is_valid_batcher_transaction(&self, tx: &Transaction) -> bool { - tx.from == self.batch_sender && tx.to.map(|to| to == self.batch_inbox).unwrap_or(false) + let batch_sender = self.config.chain.system_config.batch_sender; + let batch_inbox = self.config.chain.batch_inbox; + + tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false) } + + #[inline] + async fn get_slot_from_time(&self, time: u64) -> Result { + let mut genesis_timestamp = self.genesis_timestamp.load(Ordering::Relaxed); + let mut seconds_per_slot = self.seconds_per_slot.load(Ordering::Relaxed); + + // If we don't have data about the genesis timestamp, we need to fetch it + // from the CL first along with the "SECONDS_PER_SLOT" value from the spec. + if genesis_timestamp == 0 { + genesis_timestamp = self.fetch_beacon_genesis_timestamp().await?; + self.genesis_timestamp + .store(genesis_timestamp, Ordering::Relaxed); + + 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"))? + .as_str() + .ok_or(eyre::eyre!("Seconds per slot: expected string"))? + .parse::()?; + + if seconds_per_slot == 0 { + eyre::bail!("Seconds per slot is 0; cannot calculate slot number"); + } + + self.seconds_per_slot + .store(seconds_per_slot, Ordering::Relaxed); + } + + if time < genesis_timestamp { + eyre::bail!("Time is before genesis; cannot calculate slot number"); + } + + Ok((time - genesis_timestamp) / seconds_per_slot) + } + + async fn fetch_blob_sidecars(&self, slot: u64) -> Result> { + let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.config.l1_beacon_url); + let full_url = format!("{}/{}", base_url, slot); + + 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 blobs = serde_json::from_value::>(res.clone())?; + + Ok(blobs) + } + + async fn fetch_beacon_genesis_timestamp(&self) -> Result { + let base_url = format!("{}/eth/v1/beacon/genesis", self.config.l1_beacon_url); + + 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 genesis_time = serde_json::from_value::(res.clone())?; + + Ok(genesis_time) + } + + async fn fetch_beacon_spec(&self) -> Result { + let base_url = format!("{}/eth/v1/config/spec", self.config.l1_beacon_url); + + 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"))?; + + Ok(res.clone()) + } +} + +fn deserialize_string_to_u64<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let s: String = Deserialize::deserialize(deserializer)?; + s.parse::().map_err(serde::de::Error::custom) } #[cfg(test)] @@ -110,12 +214,14 @@ mod tests { // let Ok(l1_beacon_url) = std::env::var("L1_BEACON_TEST_RPC_URL") else { // return; // }; - let l1_beacon_url = "https://remotelab.taila355b.ts.net".to_string(); - let retriever = BlobFetcher::new(l1_beacon_url, Address::zero(), Address::zero()); - let blobs = retriever - .fetch_blob_sidecars(FetchBlobFilter::Slot(4248703)) - .await - .unwrap(); + + let config = Arc::new(Config { + l1_beacon_url: "https://remotelab.taila355b.ts.net".to_string(), + ..Default::default() + }); + + let retriever = BlobFetcher::new(config); + let blobs = retriever.fetch_blob_sidecars(4248703).await.unwrap(); assert_eq!(blobs.len(), 3); } diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index e18347cc..9bff83a7 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -166,12 +166,7 @@ impl InnerWatcher { l2_start_block: u64, ) -> Self { let provider = generate_http_provider(&config.l1_rpc_url); - - let blob_fetcher = Arc::new(BlobFetcher::new( - config.l1_beacon_url.clone(), - config.chain.batch_inbox, - config.chain.system_config.batch_sender, - )); + let blob_fetcher = Arc::new(BlobFetcher::new(Arc::clone(&config))); let system_config = if l2_start_block == config.chain.l2_genesis.number { config.chain.system_config diff --git a/src/l1/mod.rs b/src/l1/mod.rs index 09035241..166e8749 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -9,3 +9,6 @@ pub use l1_info::L1Info; pub mod blob_fetcher; pub use blob_fetcher::{BatcherTransactionData, BlobFetcher, BlobSidecar}; + +pub mod blob_encoding; +pub use blob_encoding::decode_blob_data; From 58373670511a48b0cc8e4cd77edccdd2692fb5a5 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 9 Feb 2024 21:25:39 +0100 Subject: [PATCH 05/23] chore: added test stubs --- Cargo.lock | 187 +++++++++++++++++++++++++++++++--------- Cargo.toml | 2 +- src/l1/blob_fetcher.rs | 14 +-- src/l1/chain_watcher.rs | 37 +++++++- 4 files changed, 188 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffe3b4b8..5724f803 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -680,9 +680,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.17.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", @@ -1708,9 +1708,9 @@ dependencies = [ [[package]] name = "ethers" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba3fd516c15a9a587135229466dbbfc85796de55c5660afbbb1b1c78517d85c" +checksum = "6c7cd562832e2ff584fa844cd2f6e5d4f35bbe11b28c7c9b8df957b2e1d0c701" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -1724,9 +1724,9 @@ dependencies = [ [[package]] name = "ethers-addressbook" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0245617f11b8178fa50b52e433e2c34ac69f39116b62c8be2437decf2edf1986" +checksum = "35dc9a249c066d17e8947ff52a4116406163cf92c7f0763cb8c001760b26403f" dependencies = [ "ethers-core", "once_cell", @@ -1736,9 +1736,9 @@ dependencies = [ [[package]] name = "ethers-contract" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bb80fd2c22631a5eb8a02cbf373cc5fd86937fc966bb670b9a884580c8e71c" +checksum = "43304317c7f776876e47f2f637859f6d0701c1ec7930a150f169d5fbe7d76f5a" dependencies = [ "const-hex", "ethers-contract-abigen", @@ -1755,9 +1755,9 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22c54db0d393393e732a5b20273e4f8ab89f0cce501c84e75fab9c126799a6e6" +checksum = "f9f96502317bf34f6d71a3e3d270defaa9485d754d789e15a8e04a84161c95eb" dependencies = [ "Inflector", "const-hex", @@ -1773,15 +1773,15 @@ dependencies = [ "serde", "serde_json", "syn 2.0.25", - "toml 0.7.6", + "toml 0.8.2", "walkdir", ] [[package]] name = "ethers-contract-derive" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ee4f216184a1304b707ed258f4f70aa40bf7e1522ab8963d127a8d516eaa1a" +checksum = "452ff6b0a64507ce8d67ffd48b1da3b42f03680dcf5382244e9c93822cbbf5de" dependencies = [ "Inflector", "const-hex", @@ -1795,9 +1795,9 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c29523f73c12753165781c6e5dc11c84d3e44c080a15f7c6cfbd70b514cb6f1" +checksum = "aab3cef6cc1c9fd7f787043c81ad3052eff2b96a3878ef1526aa446311bdbfc9" dependencies = [ "arrayvec", "bytes", @@ -1825,10 +1825,11 @@ dependencies = [ [[package]] name = "ethers-etherscan" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aab5af432b3fe5b7756b60df5c9ddeb85a13414575ad8a9acd707c24f0a77a5" +checksum = "16d45b981f5fa769e1d0343ebc2a44cfa88c9bc312eb681b676318b40cef6fb1" dependencies = [ + "chrono", "ethers-core", "reqwest", "semver", @@ -1840,9 +1841,9 @@ dependencies = [ [[package]] name = "ethers-middleware" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356151d5ded56d4918146366abc9dfc9df367cf0096492a7a5477b21b7693615" +checksum = "145211f34342487ef83a597c1e69f0d3e01512217a7c72cc8a25931854c7dca0" dependencies = [ "async-trait", "auto_impl", @@ -1867,9 +1868,9 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c84664b294e47fc2860d6db0db0246f79c4c724e552549631bb9505b834bee" +checksum = "fb6b15393996e3b8a78ef1332d6483c11d839042c17be58decc92fa8b1c3508a" dependencies = [ "async-trait", "auto_impl", @@ -1904,9 +1905,9 @@ dependencies = [ [[package]] name = "ethers-signers" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170b299698702ef1f53d2275af7d6d97409cfa4f9398ee9ff518f6bc9102d0ad" +checksum = "b3b125a103b56aef008af5d5fb48191984aa326b50bfd2557d231dc499833de3" dependencies = [ "async-trait", "coins-bip32", @@ -1923,9 +1924,9 @@ dependencies = [ [[package]] name = "ethers-solc" -version = "2.0.9" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66559c8f774712df303c907d087275a52a2046b256791aaa566d5abc8ea66731" +checksum = "d21df08582e0a43005018a858cc9b465c5fff9cf4056651be64f844e57d1f55f" dependencies = [ "cfg-if", "const-hex", @@ -2685,16 +2686,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.48.0", + "windows-core", ] [[package]] @@ -2759,7 +2760,7 @@ dependencies = [ "rtnetlink", "system-configuration", "tokio", - "windows 0.34.0", + "windows", ] [[package]] @@ -2918,6 +2919,15 @@ 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 = "itoa" version = "1.0.8" @@ -3086,7 +3096,7 @@ dependencies = [ "diff", "ena", "is-terminal", - "itertools", + "itertools 0.10.5", "lalrpop-util", "petgraph", "regex", @@ -4264,7 +4274,7 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec 1.11.0", - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -5698,11 +5708,11 @@ dependencies = [ [[package]] name = "solang-parser" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c792fe9fae2a2f716846f214ca10d5a1e21133e0bf36cef34bcc4a852467b21" +checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" dependencies = [ - "itertools", + "itertools 0.11.0", "lalrpop", "lalrpop-util", "phf", @@ -6203,7 +6213,19 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.12", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -6225,7 +6247,20 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.4.9", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.5.37", ] [[package]] @@ -7014,12 +7049,12 @@ dependencies = [ ] [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", ] [[package]] @@ -7028,7 +7063,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -7037,21 +7072,42 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.48.0", "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.34.0" @@ -7064,6 +7120,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.34.0" @@ -7076,6 +7138,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.34.0" @@ -7088,6 +7156,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.34.0" @@ -7100,12 +7174,24 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.34.0" @@ -7118,6 +7204,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.4.9" @@ -7127,6 +7219,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.5.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/Cargo.toml b/Cargo.toml index 2b50aeb4..b28fb01d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ path = "./bin/network.rs" tokio = { version = "1.28.0", features = ["full"] } async-trait = "0.1.73" eyre = "0.6.8" -ethers = { version = "2.0.8", features = ["optimism"] } +ethers = { version = "2.0.12", features = ["optimism"] } hex = "0.4.3" libflate = "1.2.0" openssl = { version = "0.10", features = ["vendored"] } diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index ef6801d7..9dd09366 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -61,6 +61,9 @@ impl BlobFetcher { let mut blob_index = 0; for tx in block.transactions.iter() { + let tx_blob_hashes = tx.other.get("blob_versioned_hashes"); + dbg!(tx_blob_hashes); + if !self.is_valid_batcher_transaction(tx) { blob_index += 1; // TODO: += number of actual tx.blob_hashes continue; @@ -210,18 +213,17 @@ mod tests { #[tokio::test] // TODO: update with a test from mainnet after dencun is active async fn test_get_blobs() { - // TODO: use env vars in tests - // let Ok(l1_beacon_url) = std::env::var("L1_BEACON_TEST_RPC_URL") else { - // return; - // }; + let Ok(l1_beacon_url) = std::env::var("L1_GOERLI_BEACON_RPC_URL") else { + return; + }; let config = Arc::new(Config { - l1_beacon_url: "https://remotelab.taila355b.ts.net".to_string(), + l1_beacon_url, ..Default::default() }); let retriever = BlobFetcher::new(config); - let blobs = retriever.fetch_blob_sidecars(4248703).await.unwrap(); + let blobs = retriever.fetch_blob_sidecars(7576509).await.unwrap(); assert_eq!(blobs.len(), 3); } diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index 9bff83a7..18c3fdda 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -243,10 +243,10 @@ impl InnerWatcher { let block = self.get_block(self.current_block).await?; let user_deposits = self.get_deposits(self.current_block).await?; - let finalized = self.current_block >= self.finalized_block; - let batcher_transactions = self.blob_fetcher.get_batcher_transactions(&block).await?; + let finalized = self.current_block >= self.finalized_block; + let l1_info = L1Info { system_config: self.system_config, block_info: L1BlockInfo::try_from(&block)?, @@ -453,3 +453,36 @@ fn start_watcher( Ok((handle, block_update_receiver)) } + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_batcher_transactions() { + let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { + return; + }; + + // TODO: find goerli block with batcher txs + let block_number = 19245284; + + let config = Arc::new(Config { + l1_rpc_url, + ..Default::default() + }); + let (block_update_tx, block_update_rx) = mpsc::channel(1000); + let watcher = InnerWatcher::new(config, block_update_tx, block_number, 0).await; + + let block = watcher.get_block(block_number).await.unwrap(); + assert_eq!(block.number.unwrap().as_u64(), block_number); + + let batcher_transactions = watcher + .blob_fetcher + .get_batcher_transactions(&block) + .await + .unwrap(); + + assert_eq!(batcher_transactions.len(), 1); + } +} From 8acc69e4043936037bbd9f468e432d3d7c5af4cc Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Fri, 9 Feb 2024 23:14:01 +0100 Subject: [PATCH 06/23] chore: blobs versioned hashes update --- Cargo.toml | 2 +- src/l1/blob_fetcher.rs | 21 +++++++++------------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b28fb01d..9969db44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ path = "./bin/network.rs" tokio = { version = "1.28.0", features = ["full"] } async-trait = "0.1.73" eyre = "0.6.8" -ethers = { version = "2.0.12", features = ["optimism"] } +ethers = { version = "2.0.11", features = ["optimism"] } hex = "0.4.3" libflate = "1.2.0" openssl = { version = "0.10", features = ["vendored"] } diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index 9dd09366..989a7959 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -61,20 +61,20 @@ impl BlobFetcher { let mut blob_index = 0; for tx in block.transactions.iter() { - let tx_blob_hashes = tx.other.get("blob_versioned_hashes"); + // Versioned Hash is just 32 bytes + let tx_blob_hashes: Vec = tx + .other + .get_deserialized("BlobVersionedHashes") + .unwrap_or_default(); + dbg!(tx_blob_hashes); if !self.is_valid_batcher_transaction(tx) { - blob_index += 1; // TODO: += number of actual tx.blob_hashes + blob_index += tx_blob_hashes.len(); continue; } - // sanity check: transactions here should always have a transaction type - let Some(tx_type) = tx.transaction_type.map(|t| t.as_u64()) else { - tracing::error!("found batcher tx without tx_type. This shouldn't happen."); - continue; - }; - + let tx_type = tx.transaction_type.map(|t| t.as_u64()).unwrap_or(0); if tx_type != BLOB_CARRYING_TRANSACTION_TYPE { // this is necessary because ethers-rs wraps `bytes::Bytes` into its own type // that doesn't come with free conversion back to `bytes::Bytes`. @@ -83,10 +83,7 @@ impl BlobFetcher { continue; } - // TODO: retrieve tx.blob_hashes. might need to update/fork ethers-rs. - // are there other ways to see how many blobs are in a tx? - let blob_hashes = vec![H256::zero()]; - for blob_hash in blob_hashes { + for blob_hash in tx_blob_hashes { indexed_blobs.push((blob_index, blob_hash)); blob_index += 1; } From fced110b09fed20e0aaea2cd808c04a30b175dce Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sat, 10 Feb 2024 19:19:24 +0100 Subject: [PATCH 07/23] feat: fetch and decode op-goerli batcher tx --- Cargo.lock | 2602 ++++++++++++++------------------------- src/config/mod.rs | 15 +- src/l1/blob_encoding.rs | 30 +- src/l1/blob_fetcher.rs | 72 +- src/l1/chain_watcher.rs | 33 - 5 files changed, 1013 insertions(+), 1739 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5724f803..8547c117 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -33,15 +33,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" -[[package]] -name = "aead" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" -dependencies = [ - "generic-array", -] - [[package]] name = "aead" version = "0.4.3" @@ -49,7 +40,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ "generic-array", - "rand_core 0.6.4", ] [[package]] @@ -62,17 +52,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "aes" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" -dependencies = [ - "aes-soft", - "aesni", - "cipher 0.2.5", -] - [[package]] name = "aes" version = "0.7.5" @@ -113,9 +92,9 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead 0.5.2", "aes 0.8.3", @@ -125,26 +104,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "aes-soft" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" -dependencies = [ - "cipher 0.2.5", - "opaque-debug", -] - -[[package]] -name = "aesni" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" -dependencies = [ - "cipher 0.2.5", - "opaque-debug", -] - [[package]] name = "again" version = "0.1.2" @@ -158,20 +117,20 @@ dependencies = [ [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -202,24 +161,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" - -[[package]] -name = "arc-swap" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" - -[[package]] -name = "array-init" -version = "0.0.4" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" -dependencies = [ - "nodrop", -] +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arrayref" @@ -248,48 +192,20 @@ dependencies = [ "term", ] -[[package]] -name = "asn1-rs" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33" -dependencies = [ - "asn1-rs-derive 0.1.0", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time 0.3.23", -] - [[package]] name = "asn1-rs" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" dependencies = [ - "asn1-rs-derive 0.4.0", + "asn1-rs-derive", "asn1-rs-impl", "displaydoc", "nom", "num-traits", "rusticata-macros", "thiserror", - "time 0.3.23", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", + "time", ] [[package]] @@ -323,42 +239,43 @@ checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" [[package]] name = "async-io" -version = "1.13.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" dependencies = [ "async-lock", - "autocfg", "cfg-if", "concurrent-queue", + "futures-io", "futures-lite", - "log", "parking", "polling", - "rustix 0.37.23", + "rustix", "slab", - "socket2 0.4.9", - "waker-fn", + "tracing", + "windows-sys 0.52.0", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -374,9 +291,9 @@ dependencies = [ [[package]] name = "asynchronous-codec" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182" +checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" dependencies = [ "bytes", "futures-sink", @@ -387,15 +304,12 @@ dependencies = [ [[package]] name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "atomic-waker" -version = "1.1.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] [[package]] name = "atty" @@ -410,14 +324,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -428,9 +341,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -467,9 +380,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -479,9 +392,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bech32" -version = "0.7.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] name = "beef" @@ -492,15 +405,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bit-set" version = "0.5.3" @@ -524,19 +428,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" - -[[package]] -name = "bitvec" -version = "0.17.4" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" -dependencies = [ - "either", - "radium 0.3.0", -] +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -545,7 +439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", - "radium 0.7.0", + "radium", "tap", "wyz", ] @@ -578,35 +472,26 @@ dependencies = [ ] [[package]] -name = "block-modes" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" -dependencies = [ - "block-padding", - "cipher 0.2.5", -] - -[[package]] -name = "block-padding" -version = "0.2.1" +name = "bs58" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bs58" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2 0.9.9", + "sha2 0.10.8", + "tinyvec", ] [[package]] name = "bstr" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "serde", @@ -614,9 +499,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byte-slice-cast" @@ -624,17 +509,23 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" + [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -671,9 +562,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -694,22 +585,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", -] - -[[package]] -name = "ccm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca1a8fbc20b50ac9673ff014abfb2b5f4085ee1a850d408f14a159c5853ac7" -dependencies = [ - "aead 0.3.2", - "cipher 0.2.5", - "subtle", + "libc", ] [[package]] @@ -720,58 +601,47 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chacha20" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ "cfg-if", - "cipher 0.3.0", + "cipher 0.4.4", "cpufeatures", - "zeroize", ] [[package]] name = "chacha20poly1305" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ - "aead 0.4.3", + "aead 0.5.2", "chacha20", - "cipher 0.3.0", + "cipher 0.4.4", "poly1305", "zeroize", ] [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets 0.52.0", ] [[package]] name = "chunked_transfer" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" - -[[package]] -name = "cipher" -version = "0.2.5" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" -dependencies = [ - "generic-array", -] +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" [[package]] name = "cipher" @@ -790,6 +660,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -833,86 +704,83 @@ dependencies = [ [[package]] name = "coins-bip32" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30a84aab436fcb256a2ab3c80663d8aec686e6bae12827bb05fef3e1e439c9f" +checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" dependencies = [ - "bincode", - "bs58", + "bs58 0.5.0", "coins-core", "digest 0.10.7", - "getrandom 0.2.10", "hmac 0.12.1", - "k256 0.13.1", - "lazy_static", + "k256 0.13.3", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] [[package]] name = "coins-bip39" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f4d04ee18e58356accd644896aeb2094ddeafb6a713e056cef0c0a8e468c15" +checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" dependencies = [ - "bitvec 0.17.4", + "bitvec", "coins-bip32", - "getrandom 0.2.10", "hmac 0.12.1", "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", ] [[package]] name = "coins-core" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b949a1c63fb7eb591eb7ba438746326aedf0ae843e51ec92ba6bec5bb382c4f" +checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "bech32", - "bs58", + "bs58 0.5.0", "digest 0.10.7", "generic-array", "hex", "ripemd", "serde", "serde_derive", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", ] [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" dependencies = [ "crossbeam-utils", ] [[package]] name = "const-hex" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08849ed393c907c90016652a01465a12d86361cd38ad2a7de026c56a520cc259" +checksum = "18d59688ad0945eaf6b84cb44fedbe93484c81b48970e98f09db8a22832d7961" dependencies = [ "cfg-if", "cpufeatures", "hex", + "proptest", "serde", ] [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" @@ -922,9 +790,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -932,9 +800,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core2" @@ -947,28 +815,13 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" - [[package]] name = "crc32fast" version = "1.3.2" @@ -980,46 +833,37 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -1041,9 +885,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1072,16 +916,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "ctr" version = "0.8.0" @@ -1102,12 +936,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.0" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ - "nix 0.26.2", - "windows-sys", + "nix 0.27.1", + "windows-sys 0.52.0", ] [[package]] @@ -1125,64 +959,43 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0-rc.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", "fiat-crypto", - "packed_simd_2", "platforms", + "rustc_version", "subtle", "zeroize", ] [[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.14.4" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "fnv", - "ident_case", "proc-macro2", "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "data-encoding-macro" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1190,9 +1003,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" dependencies = [ "data-encoding", "syn 1.0.109", @@ -1205,7 +1018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4355c25cbf99edcb6b4a0e906f6bdc6956eda149e84455bea49696429b2f8e8" dependencies = [ "futures", - "tokio-util 0.7.8", + "tokio-util 0.7.10", ] [[package]] @@ -1215,41 +1028,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" dependencies = [ "const-oid", - "pem-rfc7468", "zeroize", ] [[package]] name = "der" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "zeroize", ] -[[package]] -name = "der-parser" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82" -dependencies = [ - "asn1-rs 0.3.1", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "der-parser" version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" dependencies = [ - "asn1-rs 0.5.2", + "asn1-rs", "displaydoc", "nom", "num-bigint", @@ -1258,52 +1056,30 @@ dependencies = [ ] [[package]] -name = "derive_builder" -version = "0.11.2" +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ - "derive_builder_macro", + "powerfmt", ] [[package]] -name = "derive_builder_core" -version = "0.11.2" +name = "derive_more" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "darling", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] -name = "derive_builder_macro" -version = "0.11.2" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -1374,7 +1150,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1410,8 +1186,8 @@ dependencies = [ "parking_lot 0.11.2", "rand 0.8.5", "rlp", - "smallvec 1.11.0", - "socket2 0.4.9", + "smallvec", + "socket2 0.4.10", "tokio", "tokio-stream", "tokio-util 0.6.10", @@ -1429,14 +1205,14 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] name = "dtoa" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519b83cd10f5f6e969625a409f735182bea5558cd8b64c655806ceaae36f1999" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "dunce" @@ -1458,16 +1234,16 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.7", + "der 0.7.8", "digest 0.10.7", - "elliptic-curve 0.13.5", + "elliptic-curve 0.13.8", "rfc6979 0.4.0", - "signature 2.1.0", - "spki 0.7.2", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] @@ -1479,6 +1255,16 @@ dependencies = [ "signature 1.6.4", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8 0.10.2", + "signature 2.2.0", +] + [[package]] name = "ed25519-dalek" version = "1.0.1" @@ -1486,18 +1272,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ "curve25519-dalek 3.2.0", - "ed25519", + "ed25519 1.5.3", "rand 0.7.3", "serde", "sha2 0.9.9", "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek 4.1.2", + "ed25519 2.2.3", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + [[package]] name = "either" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "elliptic-curve" @@ -1512,8 +1313,6 @@ dependencies = [ "ff 0.12.1", "generic-array", "group 0.12.1", - "hkdf", - "pem-rfc7468", "pkcs8 0.9.0", "rand_core 0.6.4", "sec1 0.3.0", @@ -1523,19 +1322,19 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct 0.2.0", - "crypto-bigint 0.5.2", + "crypto-bigint 0.5.5", "digest 0.10.7", "ff 0.13.0", "generic-array", "group 0.13.0", "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1 0.7.2", + "sec1 0.7.3", "subtle", "zeroize", ] @@ -1551,9 +1350,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -1565,9 +1364,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "492a7e5fc2504d5fdce8e124d3e263b244a68b283cac67a69eda0cd43e0aebad" dependencies = [ "base64 0.13.1", - "bs58", + "bs58 0.4.0", "bytes", - "ed25519-dalek", + "ed25519-dalek 1.0.1", "hex", "k256 0.11.6", "log", @@ -1580,19 +1379,18 @@ dependencies = [ [[package]] name = "enr" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be7b2ac146c1f99fe245c02d16af0696450d8e06c135db75e10eeb9e642c20d" +checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "bytes", "hex", - "k256 0.13.1", + "k256 0.13.3", "log", "rand 0.8.5", "rlp", "serde", - "serde-hex", "sha3", "zeroize", ] @@ -1617,23 +1415,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -1652,7 +1439,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "thiserror", "uuid 0.8.2", @@ -1772,8 +1559,8 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.25", - "toml 0.8.2", + "syn 2.0.48", + "toml 0.8.10", "walkdir", ] @@ -1790,7 +1577,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -1804,10 +1591,10 @@ dependencies = [ "cargo_metadata", "chrono", "const-hex", - "elliptic-curve 0.13.5", + "elliptic-curve 0.13.8", "ethabi", "generic-array", - "k256 0.13.1", + "k256 0.13.3", "num_enum", "once_cell", "open-fastrlp", @@ -1816,7 +1603,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.25", + "syn 2.0.48", "tempfile", "thiserror", "tiny-keccak", @@ -1874,10 +1661,10 @@ checksum = "fb6b15393996e3b8a78ef1332d6483c11d839042c17be58decc92fa8b1c3508a" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.2", + "base64 0.21.7", "bytes", "const-hex", - "enr 0.9.0", + "enr 0.9.1", "ethers-core", "futures-core", "futures-timer 3.0.2", @@ -1913,11 +1700,11 @@ dependencies = [ "coins-bip32", "coins-bip39", "const-hex", - "elliptic-curve 0.13.5", + "elliptic-curve 0.13.8", "eth-keystore", "ethers-core", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -1956,34 +1743,40 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] -name = "eyre" -version = "0.6.8" +name = "event-listener-strategy" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "indenter", - "once_cell", + "event-listener", + "pin-project-lite", ] [[package]] -name = "fastrand" -version = "1.9.0" +name = "eyre" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ - "instant", + "indenter", + "once_cell", ] [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "ff" @@ -2007,20 +1800,20 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" [[package]] name = "figment" -version = "0.10.10" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4547e226f4c9ab860571e070a9034192b3175580ecea38da34fcdb53a018c9a5" +checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026" dependencies = [ "atomic", "pear", "serde", - "toml 0.7.6", + "toml 0.8.10", "uncased", "version_check", ] @@ -2045,9 +1838,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -2076,9 +1869,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -2101,9 +1894,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -2116,9 +1909,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -2136,9 +1929,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-core-preview" @@ -2148,9 +1941,9 @@ checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -2171,9 +1964,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-io-preview" @@ -2183,17 +1976,12 @@ checksum = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" [[package]] name = "futures-lite" -version = "1.13.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ - "fastrand 1.9.0", "futures-core", - "futures-io", - "memchr", - "parking", "pin-project-lite", - "waker-fn", ] [[package]] @@ -2208,13 +1996,13 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -2238,15 +2026,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" dependencies = [ "futures-io", - "rustls 0.20.8", - "webpki 0.22.0", + "rustls 0.20.9", + "webpki", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-sink-preview" @@ -2256,9 +2044,9 @@ checksum = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -2282,9 +2070,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -2346,15 +2134,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -2379,9 +2165,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -2391,15 +2177,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -2438,9 +2224,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -2448,10 +2234,10 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.2.2", "slab", "tokio", - "tokio-util 0.7.8", + "tokio-util 0.7.10", "tracing", ] @@ -2475,9 +2261,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hashers" @@ -2514,9 +2300,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] name = "hex" @@ -2532,9 +2318,9 @@ checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" [[package]] name = "hkdf" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac 0.12.1", ] @@ -2545,17 +2331,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac 0.11.1", + "crypto-mac", "digest 0.9.0", ] @@ -2581,11 +2357,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -2601,9 +2377,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -2612,9 +2388,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -2629,15 +2405,15 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -2650,7 +2426,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -2659,14 +2435,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.7", + "rustls 0.21.10", "tokio", "tokio-rustls", ] @@ -2695,7 +2471,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2707,12 +2483,6 @@ dependencies = [ "cc", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.2.3" @@ -2726,9 +2496,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2736,19 +2506,19 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.7.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" dependencies = [ "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "if-watch" -version = "3.0.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9465340214b296cd17a0009acdb890d6160010b8adf8f78a00d0d7ab270f79f" +checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ "async-io", "core-foundation", @@ -2819,12 +2589,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.3", ] [[package]] @@ -2851,63 +2621,33 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "interceptor" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e8a11ae2da61704edada656798b61c94b35ecac2c58eb955156987d5e6be90b" -dependencies = [ - "async-trait", - "bytes", - "log", - "rand 0.8.5", - "rtcp", - "rtp", - "thiserror", - "tokio", - "waitgroup", - "webrtc-srtp", - "webrtc-util", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys", -] - [[package]] name = "ipconfig" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.3", + "socket2 0.5.5", "widestring", - "windows-sys", + "windows-sys 0.48.0", "winreg", ] [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", - "windows-sys", + "hermit-abi 0.3.5", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -2930,24 +2670,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -2996,7 +2736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d814a21d9a819f8de1a41b819a263ffd68e4bb5f043d936db1c49b54684bde0a" dependencies = [ "heck", - "proc-macro-crate", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -3017,7 +2757,7 @@ dependencies = [ "soketto", "tokio", "tokio-stream", - "tokio-util 0.7.8", + "tokio-util 0.7.10", "tower", "tracing", ] @@ -3042,9 +2782,9 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -3059,28 +2799,28 @@ dependencies = [ "cfg-if", "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", - "ecdsa 0.16.7", - "elliptic-curve 0.13.5", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "once_cell", - "sha2 0.10.7", - "signature 2.1.0", + "sha2 0.10.8", + "signature 2.2.0", ] [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -3100,7 +2840,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax 0.7.4", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -3121,9 +2861,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libflate" @@ -3147,20 +2887,20 @@ dependencies = [ [[package]] name = "libm" -version = "0.1.4" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libp2p" -version = "0.51.3" +version = "0.51.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f210d259724eae82005b5c48078619b7745edb7b76de370b03f8ba59ea103097" +checksum = "f35eae38201a993ece6bdc823292d6abd1bffed1c4d0f4a3517d2bd8e1d917fe" dependencies = [ "bytes", "futures", "futures-timer 3.0.2", - "getrandom 0.2.10", + "getrandom 0.2.12", "instant", "libp2p-allow-block-list", "libp2p-connection-limits", @@ -3176,7 +2916,6 @@ dependencies = [ "libp2p-quic", "libp2p-swarm", "libp2p-tcp", - "libp2p-webrtc", "multiaddr", "pin-project", ] @@ -3227,7 +2966,7 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "rw-stream-sink", - "smallvec 1.11.0", + "smallvec", "thiserror", "unsigned-varint", "void", @@ -3243,7 +2982,7 @@ dependencies = [ "libp2p-core", "log", "parking_lot 0.12.1", - "smallvec 1.11.0", + "smallvec", "trust-dns-resolver", ] @@ -3254,7 +2993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70b34b6da8165c0bde35c82db8efda39b824776537e73973549e76cadb3a77c5" dependencies = [ "asynchronous-codec", - "base64 0.21.2", + "base64 0.21.7", "byteorder", "bytes", "either", @@ -3271,8 +3010,8 @@ dependencies = [ "quick-protobuf-codec", "rand 0.8.5", "regex", - "sha2 0.10.7", - "smallvec 1.11.0", + "sha2 0.10.8", + "smallvec", "thiserror", "unsigned-varint", "void", @@ -3281,20 +3020,20 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e2d584751cecb2aabaa56106be6be91338a60a0f4e420cf2af639204f596fc1" +checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "asn1_der", - "bs58", - "ed25519-dalek", + "bs58 0.4.0", + "ed25519-dalek 2.1.1", "libsecp256k1", "log", "multiaddr", "multihash", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "zeroize", ] @@ -3313,8 +3052,8 @@ dependencies = [ "libp2p-swarm", "log", "rand 0.8.5", - "smallvec 1.11.0", - "socket2 0.4.9", + "smallvec", + "socket2 0.4.10", "tokio", "trust-dns-proto", "void", @@ -3347,7 +3086,7 @@ dependencies = [ "nohash-hasher", "parking_lot 0.12.1", "rand 0.8.5", - "smallvec 1.11.0", + "smallvec", "unsigned-varint", ] @@ -3366,11 +3105,11 @@ dependencies = [ "once_cell", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "snow", "static_assertions", "thiserror", - "x25519-dalek 1.1.1", + "x25519-dalek", "zeroize", ] @@ -3408,7 +3147,7 @@ dependencies = [ "parking_lot 0.12.1", "quinn-proto", "rand 0.8.5", - "rustls 0.20.8", + "rustls 0.20.9", "thiserror", "tokio", ] @@ -3429,7 +3168,7 @@ dependencies = [ "libp2p-swarm-derive", "log", "rand 0.8.5", - "smallvec 1.11.0", + "smallvec", "tokio", "void", ] @@ -3457,7 +3196,7 @@ dependencies = [ "libc", "libp2p-core", "log", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", ] @@ -3471,44 +3210,24 @@ dependencies = [ "futures-rustls", "libp2p-core", "libp2p-identity", - "rcgen 0.10.0", - "ring", - "rustls 0.20.8", + "rcgen", + "ring 0.16.20", + "rustls 0.20.9", "thiserror", - "webpki 0.22.0", - "x509-parser 0.14.0", + "webpki", + "x509-parser", "yasna", ] [[package]] -name = "libp2p-webrtc" -version = "0.4.0-alpha.4" +name = "libredox" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba48592edbc2f60b4bc7c10d65445b0c3964c07df26fdf493b6880d33be36f8" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "async-trait", - "asynchronous-codec", - "bytes", - "futures", - "futures-timer 3.0.2", - "hex", - "if-watch", - "libp2p-core", - "libp2p-identity", - "libp2p-noise", - "log", - "multihash", - "quick-protobuf", - "quick-protobuf-codec", - "rand 0.8.5", - "rcgen 0.9.3", - "serde", - "stun", - "thiserror", - "tinytemplate", - "tokio", - "tokio-util 0.7.8", - "webrtc", + "bitflags 2.4.2", + "libc", + "redox_syscall 0.4.1", ] [[package]] @@ -3567,21 +3286,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -3589,9 +3302,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" @@ -3650,7 +3363,7 @@ dependencies = [ "tracing-appender", "tracing-subscriber", "unsigned-varint", - "uuid 1.4.0", + "uuid 1.7.0", ] [[package]] @@ -3674,44 +3387,21 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "md-5" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ + "cfg-if", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.6.5" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "mime" @@ -3727,22 +3417,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3788,9 +3478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" dependencies = [ "core2", - "digest 0.10.7", "multihash-derive", - "sha2 0.10.7", "unsigned-varint", ] @@ -3800,7 +3488,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", "quote", @@ -3818,7 +3506,7 @@ dependencies = [ "futures", "log", "pin-project", - "smallvec 1.11.0", + "smallvec", "unsigned-varint", ] @@ -3921,27 +3609,19 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "cfg-if", "libc", - "static_assertions", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -3970,32 +3650,38 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -4004,63 +3690,54 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.5", "libc", ] [[package]] name = "num_enum" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] name = "object" -version = "0.31.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] -[[package]] -name = "oid-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a" -dependencies = [ - "asn1-rs 0.3.1", -] - [[package]] name = "oid-registry" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" dependencies = [ - "asn1-rs 0.5.2", + "asn1-rs", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -4095,11 +3772,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "cfg-if", "foreign-types", "libc", @@ -4116,7 +3793,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -4127,18 +3804,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.26.0+1.1.1u" +version = "300.2.2+3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37" +checksum = "8bbfad0063610ac26ee79f7484739e2b07555a75c42453b89263830b5c8103bc" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" dependencies = [ "cc", "libc", @@ -4155,9 +3832,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "overload" @@ -4165,46 +3842,14 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "p256" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" -dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.7", -] - -[[package]] -name = "p384" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" -dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.7", -] - -[[package]] -name = "packed_simd_2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" -dependencies = [ - "cfg-if", - "libm", -] - [[package]] name = "parity-scale-codec" -version = "3.6.3" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756d439303e94fae44f288ba881ad29670c65b0c4b0e05674ca81061bb65f2c5" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec", - "bitvec 1.0.1", + "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", @@ -4213,11 +3858,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.3" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d884d78fcf214d70b1e239fcd1c6e5e95aa3be1881918da2e488cc946c7a476" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 1.0.109", @@ -4225,9 +3870,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -4247,7 +3892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.9", ] [[package]] @@ -4260,21 +3905,21 @@ dependencies = [ "instant", "libc", "redox_syscall 0.2.16", - "smallvec 1.11.0", + "smallvec", "winapi", ] [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "smallvec 1.11.0", - "windows-targets 0.48.1", + "redox_syscall 0.4.1", + "smallvec", + "windows-targets 0.48.5", ] [[package]] @@ -4290,9 +3935,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "path-slash" @@ -4309,7 +3954,7 @@ dependencies = [ "digest 0.10.7", "hmac 0.12.1", "password-hash", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -4324,25 +3969,25 @@ dependencies = [ [[package]] name = "pear" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" +checksum = "4ccca0f6c17acc81df8e242ed473ec144cbf5c98037e69aa6d144780aad103c8" dependencies = [ "inlinable_string", "pear_codegen", - "yansi 1.0.0-rc", + "yansi 1.0.0-rc.1", ] [[package]] name = "pear_codegen" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" +checksum = "2e22670e8eb757cff11d6c199ca7b987f352f0346e0be4dd23869ec72cb53c77" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -4354,29 +3999,20 @@ dependencies = [ "base64 0.13.1", ] -[[package]] -name = "pem-rfc7468" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap 2.2.2", ] [[package]] @@ -4419,7 +4055,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -4442,22 +4078,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -4488,47 +4124,45 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.7", - "spki 0.7.2", + "der 0.7.8", + "spki 0.7.3", ] [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "platforms" -version = "3.0.2" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "polling" -version = "2.8.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" dependencies = [ - "autocfg", - "bitflags 1.3.2", "cfg-if", "concurrent-queue", - "libc", - "log", "pin-project-lite", - "windows-sys", + "rustix", + "tracing", + "windows-sys 0.52.0", ] [[package]] name = "poly1305" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ "cpufeatures", "opaque-debug", - "universal-hash 0.4.1", + "universal-hash 0.5.1", ] [[package]] @@ -4555,6 +4189,12 @@ dependencies = [ "universal-hash 0.5.1", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -4569,19 +4209,19 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92139198957b410250d43fad93e630d956499a625c527eda65175c8680f83387" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", @@ -4601,6 +4241,24 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +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" @@ -4627,9 +4285,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -4642,9 +4300,9 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", "version_check", - "yansi 1.0.0-rc", + "yansi 1.0.0-rc.1", ] [[package]] @@ -4675,13 +4333,13 @@ dependencies = [ [[package]] name = "prometheus-client-derive-encode" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b6a5217beb0ad503ee7fa752d451c905113d70721b937126158f3106a48cc1" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -4698,6 +4356,22 @@ dependencies = [ "tiny_http", ] +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bitflags 2.4.2", + "lazy_static", + "num-traits", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax 0.8.2", + "unarray", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -4728,37 +4402,31 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c" +checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ "bytes", "rand 0.8.5", - "ring", + "ring 0.16.20", "rustc-hash", - "rustls 0.20.8", + "rustls 0.20.9", "slab", "thiserror", "tinyvec", "tracing", - "webpki 0.22.0", + "webpki", ] [[package]] name = "quote" -version = "1.0.29" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" - [[package]] name = "radium" version = "0.7.0" @@ -4824,7 +4492,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", ] [[package]] @@ -4836,11 +4504,20 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -4848,27 +4525,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "rcgen" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" -dependencies = [ - "pem", - "ring", - "time 0.3.23", - "x509-parser 0.13.2", - "yasna", ] [[package]] @@ -4878,8 +4540,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", - "ring", - "time 0.3.23", + "ring 0.16.20", + "time", "yasna", ] @@ -4894,34 +4556,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.12", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.1" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.3", - "regex-syntax 0.7.4", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -4935,13 +4597,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", ] [[package]] @@ -4952,17 +4614,23 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "regex-syntax" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.20" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ - "base64 0.21.2", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -4981,11 +4649,13 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.7", + "rustls 0.21.10", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", @@ -4994,7 +4664,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.2", + "webpki-roots", "winreg", ] @@ -5038,12 +4708,26 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom 0.2.12", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -5081,17 +4765,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "rtcp" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1919efd6d4a6a85d13388f9487549bb8e359f17198cc03ffd72f79b553873691" -dependencies = [ - "bytes", - "thiserror", - "webrtc-util", -] - [[package]] name = "rtnetlink" version = "0.10.1" @@ -5107,20 +4780,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "rtp" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a095411ff00eed7b12e4c6a118ba984d113e1079582570d56a5ee723f11f80" -dependencies = [ - "async-trait", - "bytes", - "rand 0.8.5", - "serde", - "thiserror", - "webrtc-util", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -5159,102 +4818,65 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] - -[[package]] -name = "rustix" -version = "0.38.4" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.2", "errno", "libc", - "linux-raw-sys 0.4.3", - "windows-sys", -] - -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64 0.13.1", - "log", - "ring", - "sct 0.6.1", - "webpki 0.21.4", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ "log", - "ring", - "sct 0.7.0", - "webpki 0.22.0", + "ring 0.16.20", + "sct", + "webpki", ] [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring", - "rustls-webpki 0.101.4", - "sct 0.7.0", + "ring 0.17.7", + "rustls-webpki", + "sct", ] [[package]] name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64 0.21.2", -] - -[[package]] -name = "rustls-webpki" -version = "0.100.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "ring", - "untrusted", + "base64 0.21.7", ] [[package]] name = "rustls-webpki" -version = "0.101.4" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rw-stream-sink" @@ -5269,9 +4891,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "salsa20" @@ -5293,9 +4915,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" dependencies = [ "cfg-if", "derive_more", @@ -5305,11 +4927,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn 1.0.109", @@ -5317,18 +4939,18 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scrypt" @@ -5339,39 +4961,17 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sdp" -version = "0.5.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d22a5ef407871893fd72b4562ee15e4742269b173959db4b8df6f538c414e13" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "rand 0.8.5", - "substring", - "thiserror", - "url", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -5390,12 +4990,12 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.7", + "der 0.7.8", "generic-array", "pkcs8 0.10.2", "subtle", @@ -5404,9 +5004,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -5417,9 +5017,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -5427,9 +5027,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" dependencies = [ "serde", ] @@ -5448,40 +5048,29 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-hex" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca37e3e4d1b39afd7ff11ee4e947efae85adfddf4841787bfa47c470e96dc26d" -dependencies = [ - "array-init", - "serde", - "smallvec 0.6.14", -] - [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -5490,9 +5079,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -5524,9 +5113,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -5548,9 +5137,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -5569,9 +5158,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -5597,9 +5186,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -5614,67 +5203,58 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.23", + "time", ] [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "0.6.14" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "snow" -version = "0.9.2" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" +checksum = "850948bee068e713b8ab860fe1adc4d109676ab4c3b621fd8147f06b261f2f85" dependencies = [ - "aes-gcm 0.9.4", + "aes-gcm 0.10.3", "blake2", "chacha20poly1305", - "curve25519-dalek 4.0.0-rc.1", + "curve25519-dalek 4.1.2", "rand_core 0.6.4", - "ring", + "ring 0.17.7", "rustc_version", - "sha2 0.10.7", + "sha2 0.10.8", "subtle", ] [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -5682,12 +5262,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -5726,6 +5306,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.6.0" @@ -5738,12 +5324,12 @@ dependencies = [ [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.7", + "der 0.7.8", ] [[package]] @@ -5752,7 +5338,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f923762d556417668b192ac2fdc9827ea21e6df011d8a0a7e68f3d5da095a675" dependencies = [ - "bitvec 1.0.1", + "bitvec", "hex", "num-bigint", "serde", @@ -5808,43 +5394,15 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.25", -] - -[[package]] -name = "stun" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e94b1ec00bad60e6410e058b52f1c66de3dc5fe4d62d09b3e52bb7d3b73e25" -dependencies = [ - "base64 0.13.1", - "crc", - "lazy_static", - "md-5", - "rand 0.8.5", - "ring", - "subtle", - "thiserror", - "tokio", - "url", - "webrtc-util", -] - -[[package]] -name = "substring" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" -dependencies = [ - "autocfg", + "syn 2.0.48", ] [[package]] @@ -5855,9 +5413,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "svm-rs" -version = "0.3.0" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597e3a746727984cb7ea2487b6a40726cad0dbe86628e7d429aa6b8c4c153db4" +checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" dependencies = [ "dirs 5.0.1", "fs2", @@ -5867,7 +5425,7 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "url", "zip", @@ -5886,15 +5444,21 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.6" @@ -5936,15 +5500,14 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", - "fastrand 2.0.0", - "redox_syscall 0.3.5", - "rustix 0.38.4", - "windows-sys", + "fastrand", + "rustix", + "windows-sys 0.52.0", ] [[package]] @@ -5960,9 +5523,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -5975,22 +5538,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -6005,22 +5568,14 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.23" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -6028,16 +5583,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -6059,20 +5615,10 @@ dependencies = [ "ascii", "chunked_transfer", "log", - "time 0.3.23", + "time", "url", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -6090,9 +5636,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -6102,20 +5648,20 @@ dependencies = [ "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.3", + "socket2 0.5.5", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -6134,7 +5680,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.7", + "rustls 0.21.10", "tokio", ] @@ -6151,17 +5697,17 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", - "rustls 0.21.7", + "rustls 0.21.10", "tokio", "tokio-rustls", "tungstenite", - "webpki-roots 0.23.1", + "webpki-roots", ] [[package]] @@ -6181,9 +5727,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -6206,61 +5752,58 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.19.12", + "toml_edit 0.22.4", ] [[package]] -name = "toml" -version = "0.8.2" +name = "toml_datetime" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.20.2", ] [[package]] -name = "toml_datetime" -version = "0.6.3" +name = "toml_edit" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "serde", + "indexmap 2.2.2", + "toml_datetime", + "winnow", ] [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.0.0", - "serde", - "serde_spanned", + "indexmap 2.2.2", "toml_datetime", - "winnow 0.4.9", + "winnow", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.2.2", "serde", "serde_spanned", "toml_datetime", - "winnow 0.5.37", + "winnow", ] [[package]] @@ -6288,11 +5831,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -6301,31 +5843,32 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "time 0.3.23", + "thiserror", + "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -6343,27 +5886,27 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "regex", "sharded-slab", - "smallvec 1.11.0", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -6387,8 +5930,8 @@ dependencies = [ "ipnet", "lazy_static", "rand 0.8.5", - "smallvec 1.11.0", - "socket2 0.4.9", + "smallvec", + "socket2 0.4.10", "thiserror", "tinyvec", "tokio", @@ -6409,7 +5952,7 @@ dependencies = [ "lru-cache", "parking_lot 0.12.1", "resolv-conf", - "smallvec 1.11.0", + "smallvec", "thiserror", "tokio", "tracing", @@ -6418,15 +5961,15 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e862a1c4128df0112ab625f55cd5c934bcb4312ba80b39ae4b4835a3fd58e649" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ "byteorder", "bytes", @@ -6435,37 +5978,18 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "rustls 0.21.7", + "rustls 0.21.10", "sha1", "thiserror", "url", "utf-8", ] -[[package]] -name = "turn" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4712ee30d123ec7ae26d1e1b218395a16c87cdbaf4b3925d170d684af62ea5e8" -dependencies = [ - "async-trait", - "base64 0.13.1", - "futures", - "log", - "md-5", - "rand 0.8.5", - "ring", - "stun", - "thiserror", - "tokio", - "webrtc-util", -] - [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" @@ -6479,26 +6003,32 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "uncased" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -6537,9 +6067,9 @@ dependencies = [ [[package]] name = "unsigned-varint" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" dependencies = [ "asynchronous-codec", "bytes", @@ -6551,14 +6081,20 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.5.0", "percent-encoding", ] @@ -6574,17 +6110,17 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", "serde", ] [[package]] name = "uuid" -version = "1.4.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", ] [[package]] @@ -6611,26 +6147,11 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -[[package]] -name = "waitgroup" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292" -dependencies = [ - "atomic-waker", -] - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -6651,12 +6172,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -6665,9 +6180,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -6675,24 +6190,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -6702,9 +6217,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6712,22 +6227,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-timer" @@ -6746,9 +6261,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", @@ -6756,247 +6271,19 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki" -version = "0.22.0" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring", - "untrusted", + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] name = "webpki-roots" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" -dependencies = [ - "rustls-webpki 0.100.1", -] - -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - -[[package]] -name = "webrtc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3bc9049bdb2cea52f5fd4f6f728184225bdb867ed0dc2410eab6df5bdd67bb" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "hex", - "interceptor", - "lazy_static", - "log", - "rand 0.8.5", - "rcgen 0.9.3", - "regex", - "ring", - "rtcp", - "rtp", - "rustls 0.19.1", - "sdp", - "serde", - "serde_json", - "sha2 0.10.7", - "stun", - "thiserror", - "time 0.3.23", - "tokio", - "turn", - "url", - "waitgroup", - "webrtc-data", - "webrtc-dtls", - "webrtc-ice", - "webrtc-mdns", - "webrtc-media", - "webrtc-sctp", - "webrtc-srtp", - "webrtc-util", -] - -[[package]] -name = "webrtc-data" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef36a4d12baa6e842582fe9ec16a57184ba35e1a09308307b67d43ec8883100" -dependencies = [ - "bytes", - "derive_builder", - "log", - "thiserror", - "tokio", - "webrtc-sctp", - "webrtc-util", -] - -[[package]] -name = "webrtc-dtls" -version = "0.7.1" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05" -dependencies = [ - "aes 0.6.0", - "aes-gcm 0.10.2", - "async-trait", - "bincode", - "block-modes", - "byteorder", - "ccm", - "curve25519-dalek 3.2.0", - "der-parser 8.2.0", - "elliptic-curve 0.12.3", - "hkdf", - "hmac 0.12.1", - "log", - "oid-registry 0.6.1", - "p256", - "p384", - "rand 0.8.5", - "rand_core 0.6.4", - "rcgen 0.9.3", - "ring", - "rustls 0.19.1", - "sec1 0.3.0", - "serde", - "sha1", - "sha2 0.10.7", - "signature 1.6.4", - "subtle", - "thiserror", - "tokio", - "webpki 0.21.4", - "webrtc-util", - "x25519-dalek 2.0.0-pre.1", - "x509-parser 0.13.2", -] - -[[package]] -name = "webrtc-ice" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465a03cc11e9a7d7b4f9f99870558fe37a102b65b93f8045392fef7c67b39e80" -dependencies = [ - "arc-swap", - "async-trait", - "crc", - "log", - "rand 0.8.5", - "serde", - "serde_json", - "stun", - "thiserror", - "tokio", - "turn", - "url", - "uuid 1.4.0", - "waitgroup", - "webrtc-mdns", - "webrtc-util", -] - -[[package]] -name = "webrtc-mdns" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" -dependencies = [ - "log", - "socket2 0.4.9", - "thiserror", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-media" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72e1650a8ae006017d1a5280efb49e2610c19ccc3c0905b03b648aee9554991" -dependencies = [ - "byteorder", - "bytes", - "rand 0.8.5", - "rtp", - "thiserror", -] - -[[package]] -name = "webrtc-sctp" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d47adcd9427eb3ede33d5a7f3424038f63c965491beafcc20bc650a2f6679c0" -dependencies = [ - "arc-swap", - "async-trait", - "bytes", - "crc", - "log", - "rand 0.8.5", - "thiserror", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-srtp" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6183edc4c1c6c0175f8812eefdce84dfa0aea9c3ece71c2bf6ddd3c964de3da5" -dependencies = [ - "aead 0.4.3", - "aes 0.7.5", - "aes-gcm 0.9.4", - "async-trait", - "byteorder", - "bytes", - "ctr 0.8.0", - "hmac 0.11.0", - "log", - "rtcp", - "rtp", - "sha-1", - "subtle", - "thiserror", - "tokio", - "webrtc-util", -] - -[[package]] -name = "webrtc-util" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" -dependencies = [ - "async-trait", - "bitflags 1.3.2", - "bytes", - "cc", - "ipnet", - "lazy_static", - "libc", - "log", - "nix 0.24.3", - "rand 0.8.5", - "thiserror", - "tokio", - "winapi", -] +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "widestring" @@ -7022,9 +6309,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -7037,15 +6324,21 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.34.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows_aarch64_msvc 0.34.0", - "windows_i686_gnu 0.34.0", - "windows_i686_msvc 0.34.0", - "windows_x86_64_gnu 0.34.0", - "windows_x86_64_msvc 0.34.0", + "windows-core 0.51.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -7063,22 +6356,31 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -7098,9 +6400,9 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" @@ -7110,15 +6412,9 @@ checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.34.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" @@ -7128,15 +6424,9 @@ checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.34.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" @@ -7146,15 +6436,9 @@ checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" @@ -7164,15 +6448,9 @@ checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.34.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" @@ -7182,9 +6460,9 @@ checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" @@ -7194,15 +6472,9 @@ checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.34.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" @@ -7212,18 +6484,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.5.37" +version = "0.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" +checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" dependencies = [ "memchr", ] @@ -7235,7 +6498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -7277,52 +6540,22 @@ dependencies = [ "zeroize", ] -[[package]] -name = "x25519-dalek" -version = "2.0.0-pre.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df" -dependencies = [ - "curve25519-dalek 3.2.0", - "rand_core 0.6.4", - "zeroize", -] - -[[package]] -name = "x509-parser" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" -dependencies = [ - "asn1-rs 0.3.1", - "base64 0.13.1", - "data-encoding", - "der-parser 7.0.0", - "lazy_static", - "nom", - "oid-registry 0.4.0", - "ring", - "rusticata-macros", - "thiserror", - "time 0.3.23", -] - [[package]] name = "x509-parser" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" dependencies = [ - "asn1-rs 0.5.2", + "asn1-rs", "base64 0.13.1", "data-encoding", - "der-parser 8.2.0", + "der-parser", "lazy_static", "nom", - "oid-registry 0.6.1", + "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.23", + "time", ] [[package]] @@ -7333,9 +6566,9 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "yansi" -version = "1.0.0-rc" +version = "1.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee746ad3851dd3bc40e4a028ab3b00b99278d929e48957bcb2d111874a7e43e" +checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" [[package]] name = "yasna" @@ -7343,14 +6576,14 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.23", + "time", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -7363,7 +6596,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.48", ] [[package]] @@ -7382,7 +6615,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", "sha1", - "time 0.3.23", + "time", "zstd", ] @@ -7407,11 +6640,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.9+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/src/config/mod.rs b/src/config/mod.rs index 5ba1b5eb..c9dbd840 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -105,9 +105,10 @@ pub struct CliConfig { /// The L1 RPC #[serde(skip_serializing_if = "Option::is_none")] pub l1_rpc_url: Option, - /// The L2 execution client RPC + /// The L1 beacon client RPC #[serde(skip_serializing_if = "Option::is_none")] pub l1_beacon_url: Option, + /// The L2 execution client RPC #[serde(skip_serializing_if = "Option::is_none")] pub l2_rpc_url: Option, /// The L2 engine RPC @@ -164,6 +165,8 @@ pub struct ChainConfig { pub canyon_time: u64, /// Timestamp of the delta hardfork pub delta_time: u64, + /// Timestamp of the ecotone hardfork + pub ecotone_time: u64, /// Network blocktime #[serde(default = "default_blocktime")] pub blocktime: u64, @@ -315,6 +318,7 @@ impl ChainConfig { regolith_time: 0, canyon_time: 170499240, delta_time: 1708560000, + ecotone_time: 1710781201, } } @@ -355,6 +359,7 @@ impl ChainConfig { regolith_time: 1679079600, canyon_time: 1699981200, delta_time: 1703116800, + ecotone_time: 1707238800, blocktime: 2, } } @@ -396,6 +401,7 @@ impl ChainConfig { regolith_time: 0, canyon_time: 1699981200, delta_time: 1703203200, + ecotone_time: 1708534800, blocktime: 2, } } @@ -436,6 +442,7 @@ impl ChainConfig { regolith_time: 0, canyon_time: 1704992401, delta_time: 1708560000, + ecotone_time: 1710781201, } } @@ -474,6 +481,7 @@ impl ChainConfig { regolith_time: 1683219600, canyon_time: 1699981200, delta_time: 1703116800, + ecotone_time: 1707238800, blocktime: 2, } } @@ -513,6 +521,7 @@ impl ChainConfig { regolith_time: 0, canyon_time: 1699981200, delta_time: 1703203200, + ecotone_time: 1708534800, blocktime: 2, } } @@ -571,6 +580,8 @@ pub struct ExternalChainConfig { canyon_time: u64, /// Timestamp of the delta hardfork delta_time: u64, + /// Timestamp of the ecotone hardfork + ecotone_time: u64, /// The batch inbox address batch_inbox_address: Address, /// The deposit contract address @@ -651,6 +662,7 @@ impl From for ChainConfig { regolith_time: external.regolith_time, canyon_time: external.canyon_time, delta_time: external.delta_time, + ecotone_time: external.ecotone_time, blocktime: external.block_time, l2_to_l1_message_passer: addr("0x4200000000000000000000000000000000000016"), } @@ -700,6 +712,7 @@ impl From for ExternalChainConfig { regolith_time: chain_config.regolith_time, canyon_time: chain_config.canyon_time, delta_time: chain_config.delta_time, + ecotone_time: chain_config.ecotone_time, batch_inbox_address: chain_config.batch_inbox, deposit_contract_address: chain_config.deposit_contract, l1_system_config_address: chain_config.system_config_contract, diff --git a/src/l1/blob_encoding.rs b/src/l1/blob_encoding.rs index 6121da46..992629a1 100644 --- a/src/l1/blob_encoding.rs +++ b/src/l1/blob_encoding.rs @@ -3,20 +3,28 @@ use eyre::Result; const MAX_BLOB_DATA_SIZE: usize = (4 * 31 + 3) * 1024 - 4; const ENCODING_VERSION: u8 = 0; -const VERSION_OFFSET: usize = 0; +const VERSION_OFFSET: usize = 1; const ROUNDS: usize = 1024; -pub fn decode_blob_data(blob: &Bytes) -> Result { +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!("Invalid encoding version"); + eyre::bail!( + "Blob decoding: Invalid encoding version: want {}, got {}", + ENCODING_VERSION, + blob[VERSION_OFFSET] + ); } // 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!("Invalid length"); + eyre::bail!( + "Blob decoding: Invalid length: {} exceeds maximum {}", + output_len, + MAX_BLOB_DATA_SIZE + ); } output[0..27].copy_from_slice(&blob[5..32]); @@ -46,7 +54,10 @@ pub fn decode_blob_data(blob: &Bytes) -> Result { for output_byte in output.iter().take(MAX_BLOB_DATA_SIZE).skip(output_len) { if output_byte != &0 { - eyre::bail!("Extraneous data in field element {}", output_pos / 32); + eyre::bail!( + "Blob decoding: Extraneous data in field element {}", + output_pos / 32 + ); } } @@ -54,7 +65,10 @@ pub fn decode_blob_data(blob: &Bytes) -> Result { for byte in blob.iter().skip(input_pos) { if byte != &0 { - eyre::bail!("Extraneous data in input position {}", input_pos); + eyre::bail!( + "Blob decoding: Extraneous data in input position {}", + input_pos + ); } } @@ -64,14 +78,14 @@ pub fn decode_blob_data(blob: &Bytes) -> Result { fn decode_field_element( output_pos: &mut usize, input_pos: &mut usize, - blob: &Bytes, + blob: &[u8], output: &mut [u8], ) -> Result { let result = blob[*input_pos]; // two highest order bits of the first byte of each field element should always be 0 if result & 0b1100_0000 != 0 { - eyre::bail!("Invalid field element"); + eyre::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 989a7959..fff18527 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -4,7 +4,7 @@ use std::sync::{ }; use bytes::Bytes; -use ethers::types::{Block, Transaction, H256}; +use ethers::types::{Block, Transaction}; use eyre::Result; use serde::Deserialize; use serde_json::Value; @@ -33,7 +33,8 @@ pub struct BlobFetcher { pub struct BlobSidecar { #[serde(deserialize_with = "deserialize_string_to_u64")] pub index: u64, - pub blob: Bytes, + #[serde(deserialize_with = "deserialize_blob_bytes")] + pub blob: Vec, // kzg_commitment: String, // kzg_proof: String, // signed_block_header: Value, @@ -61,14 +62,12 @@ impl BlobFetcher { let mut blob_index = 0; for tx in block.transactions.iter() { - // Versioned Hash is just 32 bytes let tx_blob_hashes: Vec = tx .other - .get_deserialized("BlobVersionedHashes") + .get_deserialized("blobVersionedHashes") + .unwrap_or(Ok(Vec::new())) .unwrap_or_default(); - dbg!(tx_blob_hashes); - if !self.is_valid_batcher_transaction(tx) { blob_index += tx_blob_hashes.len(); continue; @@ -99,7 +98,7 @@ impl BlobFetcher { let blobs = self.fetch_blob_sidecars(slot).await?; for (blob_index, blob_hash) in indexed_blobs { - let Some(blob_sidecar) = blobs.iter().find(|b| b.index == blob_index) else { + 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); @@ -179,7 +178,8 @@ impl BlobFetcher { 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 genesis_time = serde_json::from_value::(res.clone())?; + let genesis_time = res.as_str().ok_or(eyre::eyre!("Expected string"))?; + let genesis_time = genesis_time.parse::()?; Ok(genesis_time) } @@ -203,14 +203,28 @@ where s.parse::().map_err(serde::de::Error::custom) } +fn deserialize_blob_bytes<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let s: String = Deserialize::deserialize(deserializer)?; + let s = s.trim_start_matches("0x"); + let bytes = hex::decode(s).map_err(serde::de::Error::custom)?; + Ok(bytes) +} + #[cfg(test)] mod tests { + use ethers::providers::{Http, Middleware, Provider}; + use super::*; + use crate::config::ChainConfig; - #[tokio::test] // TODO: update with a test from mainnet after dencun is active + #[tokio::test] async fn test_get_blobs() { let Ok(l1_beacon_url) = std::env::var("L1_GOERLI_BEACON_RPC_URL") else { + println!("L1_GOERLI_BEACON_RPC_URL not set; skipping test"); return; }; @@ -219,9 +233,43 @@ mod tests { ..Default::default() }); - let retriever = BlobFetcher::new(config); - let blobs = retriever.fetch_blob_sidecars(7576509).await.unwrap(); + let slot_number = 7576509; + let fetcher = BlobFetcher::new(config); + let blobs = fetcher.fetch_blob_sidecars(slot_number).await.unwrap(); + + assert_eq!(blobs.len(), 6); + } + + // TODO: update with a test from mainnet after dencun is active + // also, this test will be flaky as nodes start to purge old blobs + #[tokio::test] + async fn test_get_batcher_transactions() { + let Ok(l1_beacon_url) = std::env::var("L1_GOERLI_BEACON_RPC_URL") else { + println!("L1_GOERLI_BEACON_RPC_URL not set; skipping test"); + return; + }; + let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { + println!("L1_TEST_RPC_URL not set; skipping test"); + return; + }; + + let config = Arc::new(Config { + l1_beacon_url, + chain: ChainConfig::optimism_goerli(), + ..Default::default() + }); + + let l1_block_number = 10515928; + let l1_provider = Provider::::try_from(l1_rpc_url).unwrap(); + let l1_block = l1_provider + .get_block_with_txs(l1_block_number) + .await + .unwrap() + .unwrap(); + + let fetcher = BlobFetcher::new(config); + let batcher_transactions = fetcher.get_batcher_transactions(&l1_block).await.unwrap(); - assert_eq!(blobs.len(), 3); + assert_eq!(batcher_transactions.len(), 1); } } diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index 18c3fdda..57717e49 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -453,36 +453,3 @@ fn start_watcher( Ok((handle, block_update_receiver)) } - -#[cfg(test)] -mod tests { - use super::*; - - #[tokio::test] - async fn test_batcher_transactions() { - let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { - return; - }; - - // TODO: find goerli block with batcher txs - let block_number = 19245284; - - let config = Arc::new(Config { - l1_rpc_url, - ..Default::default() - }); - let (block_update_tx, block_update_rx) = mpsc::channel(1000); - let watcher = InnerWatcher::new(config, block_update_tx, block_number, 0).await; - - let block = watcher.get_block(block_number).await.unwrap(); - assert_eq!(block.number.unwrap().as_u64(), block_number); - - let batcher_transactions = watcher - .blob_fetcher - .get_batcher_transactions(&block) - .await - .unwrap(); - - assert_eq!(batcher_transactions.len(), 1); - } -} From 4152a480553cecb0f59a8ad0ca6bcc915545eaac Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 11 Feb 2024 13:12:03 +0100 Subject: [PATCH 08/23] feat: ecotone hardfork l1 info --- src/common/attributes_deposited.rs | 255 +++++++++++++++++++++++++++++ src/common/mod.rs | 99 +---------- src/derive/state.rs | 8 +- src/driver/info.rs | 2 +- src/driver/types.rs | 79 +++++++-- 5 files changed, 326 insertions(+), 117 deletions(-) create mode 100644 src/common/attributes_deposited.rs diff --git a/src/common/attributes_deposited.rs b/src/common/attributes_deposited.rs new file mode 100644 index 00000000..c6edba7a --- /dev/null +++ b/src/common/attributes_deposited.rs @@ -0,0 +1,255 @@ +use ethers::{ + types::{Bytes, H256, U256}, + utils::keccak256, +}; +use eyre::Result; +use lazy_static::lazy_static; + +#[derive(Debug)] +pub struct AttributesDepositedCall { + pub number: u64, + pub timestamp: u64, + pub basefee: U256, + pub hash: H256, + pub sequence_number: u64, + pub batcher_hash: H256, + pub fee_overhead: U256, + pub fee_scalar: U256, + + pub blob_base_fee_scalar: u32, + pub blob_base_fee: U256, +} + +const L1_INFO_BEDROCK_LEN: usize = 4 + 32 * 8; +const L1_INFO_BEDROCK_SIGNATURE: &str = + "setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)"; + +const L1_INFO_ECOTONE_LEN: usize = 4 + 32 * 5; +const L1_INFO_ECOTONE_SIGNATURE: &str = "setL1BlockValuesEcotone()"; + +lazy_static! { + static ref SET_L1_BLOCK_VALUES_BEDROCK_SELECTOR: [u8; 4] = keccak256(L1_INFO_BEDROCK_SIGNATURE) + [..4] + .try_into() + .unwrap(); + static ref SET_L1_BLOCK_VALUES_ECOTONE_SELECTOR: [u8; 4] = keccak256(L1_INFO_ECOTONE_SIGNATURE) + [..4] + .try_into() + .unwrap(); +} + +// static SET_L1_BLOCK_VALUES_BEDROCK_SELECTOR: [u8; 4] = keccak256("setL1BlockValues")[..4].try_into().unwrap(); +// static SET_L1_BLOCK_VALUES_ECOTONE_SELECTOR: Lazy<[u8; 4]> = Lazy::new(|| { +// keccak256("setL1BlockValuesEcotone")[..4] +// .try_into() +// .unwrap() +// }); + +impl AttributesDepositedCall { + /// Bedrock Binary Format + /// ```md + /// +---------+--------------------------+ + /// | Bytes | Field | + /// +---------+--------------------------+ + /// | 4 | Function signature | + /// | 32 | Number | + /// | 32 | Time | + /// | 32 | BaseFee | + /// | 32 | BlockHash | + /// | 32 | SequenceNumber | + /// | 32 | BatcherHash | + /// | 32 | L1FeeOverhead | + /// | 32 | L1FeeScalar | + /// +---------+--------------------------+ + /// ``` + pub fn try_from_bedrock(calldata: Bytes) -> Result { + let mut cursor = 0; + + if calldata.len() != L1_INFO_BEDROCK_LEN { + eyre::bail!("invalid calldata length"); + } + + let selector = &calldata[cursor..cursor + 4]; + if selector != *SET_L1_BLOCK_VALUES_BEDROCK_SELECTOR { + eyre::bail!("invalid selector"); + } + cursor += 4; + + let number = U256::from_big_endian(calldata[cursor..cursor + 32].try_into()?); + let number = number.as_u64(); // down-casting to u64 is safe for the block number + cursor += 32; + + let timestamp = U256::from_big_endian(calldata[cursor..cursor + 32].try_into()?); + let timestamp = timestamp.as_u64(); // down-casting to u64 is safe for UNIX timestamp + cursor += 32; + + let basefee = U256::from_big_endian(&calldata[cursor..cursor + 32]); + cursor += 32; + + let hash = H256::from_slice(&calldata[cursor..cursor + 32]); + cursor += 32; + + let sequence_number = U256::from_big_endian(calldata[cursor..cursor + 32].try_into()?); + let sequence_number = sequence_number.as_u64(); // down-casting to u64 is safe for the sequence number + cursor += 32; + + let batcher_hash = H256::from_slice(&calldata[cursor..cursor + 32]); + cursor += 32; + + let fee_overhead = U256::from_big_endian(&calldata[cursor..cursor + 32]); + cursor += 32; + + let fee_scalar = U256::from_big_endian(&calldata[cursor..cursor + 32]); + + Ok(Self { + number, + timestamp, + basefee, + hash, + sequence_number, + batcher_hash, + fee_overhead, + fee_scalar, + + // Ecotone fields are not present in Bedrock blocks + blob_base_fee_scalar: 0, + blob_base_fee: U256::zero(), + }) + } + + /// Ecotone Binary Format + /// ```md + /// +---------+--------------------------+ + /// | Bytes | Field | + /// +---------+--------------------------+ + /// | 4 | Function signature | + /// | 4 | BaseFeeScalar | + /// | 4 | BlobBaseFeeScalar | + /// | 8 | SequenceNumber | + /// | 8 | Timestamp | + /// | 8 | L1BlockNumber | + /// | 32 | BaseFee | + /// | 32 | BlobBaseFee | + /// | 32 | BlockHash | + /// | 32 | BatcherHash | + /// +---------+--------------------------+ + /// ``` + pub fn try_from_ecotone(calldata: Bytes) -> Result { + let mut cursor = 0; + + if calldata.len() != L1_INFO_ECOTONE_LEN { + eyre::bail!("invalid calldata length"); + } + + let selector = &calldata[cursor..cursor + 4]; + if selector != *SET_L1_BLOCK_VALUES_ECOTONE_SELECTOR { + eyre::bail!("invalid selector"); + } + cursor += 4; + + let fee_scalar = u32::from_be_bytes(calldata[cursor..cursor + 4].try_into()?); + let fee_scalar = U256::from(fee_scalar); // up-casting for backwards compatibility + cursor += 4; + + let blob_base_fee_scalar = u32::from_be_bytes(calldata[cursor..cursor + 4].try_into()?); + cursor += 4; + + let sequence_number = u64::from_be_bytes(calldata[cursor..cursor + 8].try_into()?); + cursor += 8; + + let timestamp = u64::from_be_bytes(calldata[cursor..cursor + 8].try_into()?); + cursor += 8; + + let number = u64::from_be_bytes(calldata[cursor..cursor + 8].try_into()?); + cursor += 8; + + let basefee = U256::from_big_endian(&calldata[cursor..cursor + 32]); + cursor += 32; + + let blob_base_fee = U256::from_big_endian(&calldata[cursor..cursor + 32]); + cursor += 32; + + let hash = H256::from_slice(&calldata[cursor..cursor + 32]); + cursor += 32; + + let batcher_hash = H256::from_slice(&calldata[cursor..cursor + 32]); + + Ok(Self { + number, + timestamp, + basefee, + hash, + sequence_number, + batcher_hash, + fee_overhead: U256::zero(), + fee_scalar, + blob_base_fee, + blob_base_fee_scalar, + }) + } +} + +#[cfg(test)] +mod tests { + mod attributed_deposited_call { + use std::str::FromStr; + + use ethers::types::{Bytes, H256, U256}; + + use crate::common::AttributesDepositedCall; + + #[test] + fn decode_from_bytes_bedrock() -> eyre::Result<()> { + // Arrange + let calldata = "0x015d8eb900000000000000000000000000000000000000000000000000000000008768240000000000000000000000000000000000000000000000000000000064443450000000000000000000000000000000000000000000000000000000000000000e0444c991c5fe1d7291ff34b3f5c3b44ee861f021396d33ba3255b83df30e357d00000000000000000000000000000000000000000000000000000000000000050000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"; + + let expected_hash = + H256::from_str("0444c991c5fe1d7291ff34b3f5c3b44ee861f021396d33ba3255b83df30e357d")?; + let expected_block_number = 8874020; + let expected_timestamp = 1682191440; + + // Act + let call = AttributesDepositedCall::try_from_bedrock(Bytes::from_str(calldata)?); + + // Assert + assert!(call.is_ok()); + let call = call.unwrap(); + + assert_eq!(call.hash, expected_hash); + assert_eq!(call.number, expected_block_number); + assert_eq!(call.timestamp, expected_timestamp); + + Ok(()) + } + + #[test] + fn decode_from_bytes_ecotone() -> eyre::Result<()> { + // Arrange + // https://goerli-optimism.etherscan.io/tx/0xc2288c5d1f6123406bfe8662bdbc1a3c999394da2e6f444f5aa8df78136f36ba + let calldata = "0x440a5e2000001db0000d273000000000000000050000000065c8ad6c0000000000a085a20000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000041dfd80f2c8af7d7ba1c1a3962026e5c96b9105d528f8fed65c56cfa731a8751c7f712eb70000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9"; + + let expected_hash = H256::from_str( + "0xc8af7d7ba1c1a3962026e5c96b9105d528f8fed65c56cfa731a8751c7f712eb7", + ); + let expected_block_number = 10519970; + let expected_timestamp = 1707650412; + let expected_blob_base_fee_scalar = 862000; + let expected_blob_base_fee = U256::from(17683022066u64); + + // Act + let call = AttributesDepositedCall::try_from_ecotone(Bytes::from_str(calldata)?); + + // Assert + assert!(call.is_ok()); + let call = call.unwrap(); + + assert_eq!(call.hash, expected_hash?); + assert_eq!(call.number, expected_block_number); + assert_eq!(call.timestamp, expected_timestamp); + assert_eq!(call.blob_base_fee_scalar, expected_blob_base_fee_scalar); + assert_eq!(call.blob_base_fee, expected_blob_base_fee); + + Ok(()) + } + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index d671aea0..010d3477 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,9 +1,7 @@ use std::fmt::Debug; use ethers::{ - abi::parse_abi_str, - prelude::BaseContract, - types::{Block, Bytes, Transaction, H256, U256}, + types::{Block, Transaction, H256}, utils::rlp::{Decodable, DecoderError, Rlp}, }; use eyre::Result; @@ -11,6 +9,8 @@ use figment::value::{Dict, Tag, Value}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use crate::engine::ExecutionPayload; +pub mod attributes_deposited; +pub use attributes_deposited::AttributesDepositedCall; /// Selected block header info #[derive(Debug, Clone, Copy, Eq, PartialEq, Default, Serialize, Deserialize)] @@ -97,64 +97,6 @@ impl From<&ExecutionPayload> for BlockInfo { } } -/// Represents the `setL1BlockValues` transaction inputs included in the first transaction of every L2 block. -pub struct AttributesDepositedCall { - /// The L1 block number of the corresponding epoch this belongs to. - pub number: u64, - /// The L1 block timestamp of the corresponding epoch this belongs to. - pub timestamp: u64, - /// The L1 block basefee of the corresponding epoch this belongs to. - pub basefee: U256, - /// The L1 block hash of the corresponding epoch this belongs to. - pub hash: H256, - /// The L2 block's position within the epoch. - pub sequence_number: u64, - /// A versioned hash of the current authorized batcher sender. - pub batcher_hash: H256, - /// The current L1 fee overhead to apply to L2 transactions cost computation. Unused after Ecotone hard fork. - pub fee_overhead: U256, - /// The current L1 fee scalar to apply to L2 transactions cost computation. Unused after Ecotone hard fork. - pub fee_scalar: U256, -} - -/// A type alias for the `setL1BlockValues` function parameter types -type SetL1BlockValueInput = (u64, u64, U256, H256, u64, H256, U256, U256); -/// The `setL1BlockValues` human-readable ABI -const L1_BLOCK_CONTRACT_ABI: &str = r#"[ - function setL1BlockValues(uint64 _number,uint64 _timestamp, uint256 _basefee, bytes32 _hash,uint64 _sequenceNumber,bytes32 _batcherHash,uint256 _l1FeeOverhead,uint256 _l1FeeScalar) external -]"#; - -impl TryFrom for AttributesDepositedCall { - type Error = eyre::Report; - - /// Decodes and converts the given bytes (calldata) into [AttributesDepositedCall]. - fn try_from(value: Bytes) -> Result { - let abi = BaseContract::from(parse_abi_str(L1_BLOCK_CONTRACT_ABI)?); - - let ( - number, - timestamp, - basefee, - hash, - sequence_number, - batcher_hash, - fee_overhead, - fee_scalar, - ): SetL1BlockValueInput = abi.decode("setL1BlockValues", value)?; - - Ok(Self { - number, - timestamp, - basefee, - hash, - sequence_number, - batcher_hash, - fee_overhead, - fee_scalar, - }) - } -} - impl From<&AttributesDepositedCall> for Epoch { /// Converts [AttributesDepositedCall] to an [Epoch] consisting of the number, hash & timestamp of the corresponding L1 epoch block. fn from(call: &AttributesDepositedCall) -> Self { @@ -193,38 +135,3 @@ impl<'de> Deserialize<'de> for RawTransaction { Ok(RawTransaction(hex::decode(tx).map_err(D::Error::custom)?)) } } - -#[cfg(test)] -mod tests { - mod attributed_deposited_call { - use std::str::FromStr; - - use ethers::types::{Bytes, H256}; - - use crate::common::AttributesDepositedCall; - - #[test] - fn decode_from_bytes() -> eyre::Result<()> { - // Arrange - let calldata = "0x015d8eb900000000000000000000000000000000000000000000000000000000008768240000000000000000000000000000000000000000000000000000000064443450000000000000000000000000000000000000000000000000000000000000000e0444c991c5fe1d7291ff34b3f5c3b44ee861f021396d33ba3255b83df30e357d00000000000000000000000000000000000000000000000000000000000000050000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240"; - - let expected_hash = - H256::from_str("0444c991c5fe1d7291ff34b3f5c3b44ee861f021396d33ba3255b83df30e357d")?; - let expected_block_number = 8874020; - let expected_timestamp = 1682191440; - - // Act - let call = AttributesDepositedCall::try_from(Bytes::from_str(calldata)?); - - // Assert - assert!(call.is_ok()); - let call = call.unwrap(); - - assert_eq!(call.hash, expected_hash); - assert_eq!(call.number, expected_block_number); - assert_eq!(call.timestamp, expected_timestamp); - - Ok(()) - } - } -} diff --git a/src/derive/state.rs b/src/derive/state.rs index 4eb89dc9..6db1f092 100644 --- a/src/derive/state.rs +++ b/src/derive/state.rs @@ -173,13 +173,15 @@ async fn l2_refs( let mut refs = BTreeMap::new(); for i in start..=head_num { - let block = provider.get_block_with_txs(i).await; - if let Ok(Some(block)) = block { - if let Ok(head_info) = HeadInfo::try_from(block) { + let l2_block = provider.get_block_with_txs(i).await; + if let Ok(Some(l2_block)) = l2_block { + if let Ok(head_info) = HeadInfo::try_from_l2_block(config, l2_block) { refs.insert( head_info.l2_block_info.number, (head_info.l2_block_info, head_info.l1_epoch), ); + } else { + tracing::warn!("could not get head info for L2 block {}", i); } } } diff --git a/src/driver/info.rs b/src/driver/info.rs index 73e5b873..cecf9e37 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -48,7 +48,7 @@ impl HeadInfoQuery { .await .ok() .flatten() - .and_then(|block| HeadInfo::try_from(block).ok()) + .and_then(|l2_block| HeadInfo::try_from_l2_block(config, l2_block).ok()) .unwrap_or_else(|| { tracing::warn!("could not get head info. Falling back to the genesis head."); HeadInfo { diff --git a/src/driver/types.rs b/src/driver/types.rs index 7cda6b92..184b067b 100644 --- a/src/driver/types.rs +++ b/src/driver/types.rs @@ -2,7 +2,10 @@ use ethers::types::{Block, Transaction}; use eyre::Result; use serde::{Deserialize, Serialize}; -use crate::common::{AttributesDepositedCall, BlockInfo, Epoch}; +use crate::{ + common::{AttributesDepositedCall, BlockInfo, Epoch}, + config::Config, +}; /// Block info for the current head of the chain #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -15,33 +18,75 @@ pub struct HeadInfo { pub sequence_number: u64, } -impl TryFrom> for HeadInfo { - type Error = eyre::Report; +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 { + if is_ecotone_but_not_first_block(config, l2_block.timestamp.as_u64()) { + HeadInfo::try_from_ecotone(l2_block) + } else { + HeadInfo::try_from_bedrock(l2_block) + } + } + + /// 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) -> Result { + let Some(first_tx) = block.transactions.first() else { + return Err(eyre::eyre!( + "Could not find the L1 attributes deposited transaction" + )); + }; + + let tx_calldata = first_tx.input.clone(); + let call = AttributesDepositedCall::try_from_bedrock(tx_calldata)?; + + Ok(Self { + l2_block_info: block.try_into()?, + l1_epoch: Epoch::from(&call), + sequence_number: call.sequence_number, + }) + } /// Returns `HeadInfo` consisting of the L2 block, the L1 epoch block it belongs to, and the L2 block's position in the epoch. - fn try_from(value: Block) -> Result { - let tx_calldata = value - .transactions - .first() - .ok_or(eyre::eyre!( + /// This function is used when the L2 block is from the Ecotone hardfork or later. + fn try_from_ecotone(block: Block) -> Result { + let Some(first_tx) = block.transactions.first() else { + return Err(eyre::eyre!( "Could not find the L1 attributes deposited transaction" - ))? - .input - .clone(); + )); + }; - let call = AttributesDepositedCall::try_from(tx_calldata)?; + let tx_calldata = first_tx.input.clone(); + let call = AttributesDepositedCall::try_from_ecotone(tx_calldata)?; Ok(Self { - l2_block_info: value.try_into()?, + l2_block_info: block.try_into()?, l1_epoch: Epoch::from(&call), sequence_number: call.sequence_number, }) } } +/// 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. +fn is_ecotone_but_not_first_block(config: &Config, block_time: u64) -> bool { + let is_ecotone = block_time >= config.chain.ecotone_time; + + if block_time < config.chain.blocktime { + return is_ecotone; + } + + let is_ecotone_activation_block = + block_time - config.chain.blocktime < config.chain.ecotone_time; + + is_ecotone && !is_ecotone_activation_block +} + #[cfg(test)] mod tests { - mod head_info { + mod head_info_bedrock { use crate::driver::HeadInfo; use std::str::FromStr; @@ -84,7 +129,7 @@ mod tests { let block: Block = serde_json::from_str(raw_block)?; // Act - let head = HeadInfo::try_from(block); + let head = HeadInfo::try_from_bedrock(block); // Assert assert!(head.is_err()); @@ -160,7 +205,7 @@ mod tests { let expected_l1_epoch_timestamp = 1682191440; // Act - let head = HeadInfo::try_from(block); + let head = HeadInfo::try_from_bedrock(block); // Assert assert!(head.is_ok()); @@ -204,7 +249,7 @@ mod tests { let provider = Provider::try_from(l2_rpc)?; let l2_block = provider.get_block_with_txs(l2_block_hash).await?.unwrap(); - let head = HeadInfo::try_from(l2_block)?; + let head = HeadInfo::try_from_bedrock(l2_block)?; let HeadInfo { l2_block_info, From 8d224688aa54ca9946dc7aaf91adaae6c4afc1d8 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 11 Feb 2024 16:00:26 +0100 Subject: [PATCH 09/23] feat: ecotone upgrade transactions --- src/common/attributes_deposited.rs | 14 +--- src/config/mod.rs | 17 ++++ src/derive/ecotone_upgrade.rs | 123 +++++++++++++++++++++++++++++ src/derive/mod.rs | 4 + src/derive/stages/attributes.rs | 19 ++++- src/driver/types.rs | 34 +++----- src/engine/payload.rs | 2 + 7 files changed, 179 insertions(+), 34 deletions(-) create mode 100644 src/derive/ecotone_upgrade.rs diff --git a/src/common/attributes_deposited.rs b/src/common/attributes_deposited.rs index c6edba7a..decabc34 100644 --- a/src/common/attributes_deposited.rs +++ b/src/common/attributes_deposited.rs @@ -15,7 +15,6 @@ pub struct AttributesDepositedCall { pub batcher_hash: H256, pub fee_overhead: U256, pub fee_scalar: U256, - pub blob_base_fee_scalar: u32, pub blob_base_fee: U256, } @@ -38,13 +37,6 @@ lazy_static! { .unwrap(); } -// static SET_L1_BLOCK_VALUES_BEDROCK_SELECTOR: [u8; 4] = keccak256("setL1BlockValues")[..4].try_into().unwrap(); -// static SET_L1_BLOCK_VALUES_ECOTONE_SELECTOR: Lazy<[u8; 4]> = Lazy::new(|| { -// keccak256("setL1BlockValuesEcotone")[..4] -// .try_into() -// .unwrap() -// }); - impl AttributesDepositedCall { /// Bedrock Binary Format /// ```md @@ -111,7 +103,7 @@ impl AttributesDepositedCall { fee_overhead, fee_scalar, - // Ecotone fields are not present in Bedrock blocks + // Ecotone fields are not present in Bedrock attributes deposited calls blob_base_fee_scalar: 0, blob_base_fee: U256::zero(), }) @@ -181,10 +173,12 @@ impl AttributesDepositedCall { hash, sequence_number, batcher_hash, - fee_overhead: U256::zero(), fee_scalar, blob_base_fee, blob_base_fee_scalar, + + // The pre-Ecotone L1 fee overhead value is dropped in Ecotone + fee_overhead: U256::zero(), }) } } diff --git a/src/config/mod.rs b/src/config/mod.rs index c9dbd840..e9b8b0f0 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -280,6 +280,23 @@ impl ChainConfig { } } + /// Returns true if the block is the first block subject to the Ecotone hardfork + pub fn is_ecotone_activation_block(&self, block_time: u64) -> bool { + if block_time < self.blocktime { + return false; + } + + block_time - self.blocktime < 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, block_time: u64) -> bool { + let is_ecotone = block_time >= self.ecotone_time; + + is_ecotone && !self.is_ecotone_activation_block(block_time) + } + /// [ChainConfig] for Optimism pub fn optimism() -> Self { Self { diff --git a/src/derive/ecotone_upgrade.rs b/src/derive/ecotone_upgrade.rs new file mode 100644 index 00000000..766c713d --- /dev/null +++ b/src/derive/ecotone_upgrade.rs @@ -0,0 +1,123 @@ +use std::str::FromStr; + +use ethers::types::{Address, Bytes, Transaction, H256, U256, U64}; + +use crate::common::RawTransaction; + +/// 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); + + let deploy_l1_block = Transaction { + transaction_type: Some(U64::from(0x7E)), + source_hash: H256::from_str( + "0x877a6077205782ea15a6dc8699fa5ebcec5e0f4389f09cb8eda09488231346f8", + ) + .unwrap(), + from: Address::from_str("0x4210000000000000000000000000000000000000").unwrap(), + to: None, + mint: None, + value: U256::from(0), + gas: U256::from(375_000), + 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: H256::from_str( + "0xa312b4510adf943510f05fcc8f15f86995a5066bd83ce11384688ae20e6ecf42", + ) + .unwrap(), + from: Address::from_str("0x4210000000000000000000000000000000000001").unwrap(), + to: None, + mint: None, + value: U256::from(0), + gas: U256::from(1_000_000), + 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: H256::from_str( + "0x18acb38c5ff1c238a7460ebc1b421fa49ec4874bdf1e0a530d234104e5e67dbc", + ) + .unwrap(), + from: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), + to: Some(Address::from_str("0x4200000000000000000000000000000000000015").unwrap()), + mint: None, + value: U256::from(0), + gas: U256::from(50_000), + 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: H256::from_str( + "0xee4f9385eceef498af0be7ec5862229f426dec41c8d42397c7257a5117d9230a", + ) + .unwrap(), + from: Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), + to: Some(Address::from_str("0x420000000000000000000000000000000000000F").unwrap()), + mint: None, + value: U256::from(0), + gas: U256::from(50_000), + 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: H256::from_str( + "0x0c1cb38e99dbc9cbfab3bb80863380b0905290b37eb3d6ab18dc01c1f3e75f93", + ) + .unwrap(), + from: Address::from_str("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001").unwrap(), + to: Some(Address::from_str("0x420000000000000000000000000000000000000F").unwrap()), + mint: None, + value: U256::from(0), + gas: U256::from(80_000), + 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: H256::from_str( + "0x69b763c48478b9dc2f65ada09b3d92133ec592ea715ec65ad6e7f3dc519dc00c", + ) + .unwrap(), + from: Address::from_str("0x0B799C86a49DEeb90402691F1041aa3AF2d3C875").unwrap(), + to: None, + mint: None, + value: U256::from(0), + gas: U256::from(0x3d090), + is_system_tx: false, + input: Bytes::from_str("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500").unwrap(), + ..Default::default() + }; + upgrade_transactions.push(RawTransaction(deploy_eip4788.rlp().to_vec())); + + upgrade_transactions +} diff --git a/src/derive/mod.rs b/src/derive/mod.rs index 0180cc1c..91447f01 100644 --- a/src/derive/mod.rs +++ b/src/derive/mod.rs @@ -20,6 +20,10 @@ pub mod stages; /// A module that keeps track of the current derivation state, caching previous L1 and L2 blocks pub mod 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 use purgeable::PurgeableIterator; diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index d4bec3bf..fe2642ec 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -9,7 +9,7 @@ use eyre::Result; use crate::common::{Epoch, RawTransaction}; use crate::config::{Config, SystemAccounts}; use crate::derive::state::State; -use crate::derive::PurgeableIterator; +use crate::derive::{get_ecotone_upgrade_transactions, PurgeableIterator}; use crate::engine::PayloadAttributes; use crate::l1::L1Info; @@ -95,6 +95,8 @@ impl Attributes { let transactions = Some(self.derive_transactions(input, l1_info)); let suggested_fee_recipient = SystemAccounts::default().fee_vault; + let parent_beacon_block_root = None; // TODO(nicolas) + PayloadAttributes { timestamp, prev_randao, @@ -106,6 +108,7 @@ impl Attributes { epoch, l1_inclusion_block, seq_number, + parent_beacon_block_root, } } @@ -121,14 +124,28 @@ impl Attributes { ) -> Vec { let mut transactions = Vec::new(); + // L1 info (attributes deposited) transaction, present in every block let attributes_tx = self.derive_attributes_deposited(l1_info, input.timestamp); transactions.push(attributes_tx); + // User deposit transactions, present in the first block of every epoch if self.sequence_number == 0 { let mut user_deposited_txs = self.derive_user_deposited(); transactions.append(&mut user_deposited_txs); } + // Optional Ecotone upgrade transactions + if self + .config + .chain + .is_ecotone_activation_block(input.timestamp) + { + let mut ecotone_upgrade_txs = get_ecotone_upgrade_transactions(); + transactions.append(&mut ecotone_upgrade_txs); + tracing::debug!("found Ecotone activation block; Upgrade transactions added"); + } + + // Remaining transactions let mut rest = input.transactions; transactions.append(&mut rest); diff --git a/src/driver/types.rs b/src/driver/types.rs index 184b067b..3b916c8b 100644 --- a/src/driver/types.rs +++ b/src/driver/types.rs @@ -23,16 +23,19 @@ impl HeadInfo { /// 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 { - if is_ecotone_but_not_first_block(config, l2_block.timestamp.as_u64()) { - HeadInfo::try_from_ecotone(l2_block) + if config + .chain + .is_ecotone_but_not_first_block(l2_block.timestamp.as_u64()) + { + HeadInfo::try_from_ecotone_block(l2_block) } else { - HeadInfo::try_from_bedrock(l2_block) + HeadInfo::try_from_bedrock_block(l2_block) } } /// 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) -> Result { + fn try_from_bedrock_block(block: Block) -> Result { let Some(first_tx) = block.transactions.first() else { return Err(eyre::eyre!( "Could not find the L1 attributes deposited transaction" @@ -51,7 +54,7 @@ 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) -> Result { + fn try_from_ecotone_block(block: Block) -> Result { let Some(first_tx) = block.transactions.first() else { return Err(eyre::eyre!( "Could not find the L1 attributes deposited transaction" @@ -69,21 +72,6 @@ impl HeadInfo { } } -/// 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. -fn is_ecotone_but_not_first_block(config: &Config, block_time: u64) -> bool { - let is_ecotone = block_time >= config.chain.ecotone_time; - - if block_time < config.chain.blocktime { - return is_ecotone; - } - - let is_ecotone_activation_block = - block_time - config.chain.blocktime < config.chain.ecotone_time; - - is_ecotone && !is_ecotone_activation_block -} - #[cfg(test)] mod tests { mod head_info_bedrock { @@ -129,7 +117,7 @@ mod tests { let block: Block = serde_json::from_str(raw_block)?; // Act - let head = HeadInfo::try_from_bedrock(block); + let head = HeadInfo::try_from_bedrock_block(block); // Assert assert!(head.is_err()); @@ -205,7 +193,7 @@ mod tests { let expected_l1_epoch_timestamp = 1682191440; // Act - let head = HeadInfo::try_from_bedrock(block); + let head = HeadInfo::try_from_bedrock_block(block); // Assert assert!(head.is_ok()); @@ -249,7 +237,7 @@ mod tests { let provider = Provider::try_from(l2_rpc)?; let l2_block = provider.get_block_with_txs(l2_block_hash).await?.unwrap(); - let head = HeadInfo::try_from_bedrock(l2_block)?; + let head = HeadInfo::try_from_bedrock_block(l2_block)?; let HeadInfo { l2_block_info, diff --git a/src/engine/payload.rs b/src/engine/payload.rs index cc25bb59..1c0352cc 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -106,6 +106,8 @@ pub struct PayloadAttributes { /// to Canyon, this value is always None. After Canyon it is an empty array. Note that we use /// the () type here since we never have a non empty array. pub withdrawals: Option>, + /// Optional extension enabled in Ecotone and later, containing the block root of the parent beacon block. + pub parent_beacon_block_root: Option, /// The batch epoch number from derivation. This value is not expected by the engine is skipped /// during serialization and deserialization. #[serde(skip)] From b3efb25a6642054d0f0b2b0a56d1118867add65e Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 11 Feb 2024 18:18:38 +0100 Subject: [PATCH 10/23] wip: parent beacon block root in v3 block handler --- src/derive/stages/attributes.rs | 3 - src/engine/payload.rs | 8 +- src/l1/l1_info.rs | 5 ++ src/network/handlers/block_handler.rs | 122 ++++++++++++++++++++++---- 4 files changed, 116 insertions(+), 22 deletions(-) diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index fe2642ec..75e6f6eb 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -95,8 +95,6 @@ impl Attributes { let transactions = Some(self.derive_transactions(input, l1_info)); let suggested_fee_recipient = SystemAccounts::default().fee_vault; - let parent_beacon_block_root = None; // TODO(nicolas) - PayloadAttributes { timestamp, prev_randao, @@ -108,7 +106,6 @@ impl Attributes { epoch, l1_inclusion_block, seq_number, - parent_beacon_block_root, } } diff --git a/src/engine/payload.rs b/src/engine/payload.rs index 1c0352cc..e9bb762d 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -42,6 +42,10 @@ pub struct ExecutionPayload { /// An array of beaconchain withdrawals. Always empty as this exists only for L1 compatibility #[serde(skip_serializing_if = "Option::is_none")] pub withdrawals: Option>, + /// None if not present (pre-Ecotone) + pub blob_gas_used: Option, + /// None if not present (pre-Ecotone) + pub excess_blob_gas: Option, } impl TryFrom> for ExecutionPayload { @@ -76,6 +80,8 @@ impl TryFrom> for ExecutionPayload { block_hash: value.hash.unwrap(), transactions: encoded_txs, withdrawals: Some(Vec::new()), + blob_gas_used: value.blob_gas_used.map(|v| v.as_u64().into()), + excess_blob_gas: value.excess_blob_gas.map(|v| v.as_u64().into()), }) } } @@ -106,8 +112,6 @@ pub struct PayloadAttributes { /// to Canyon, this value is always None. After Canyon it is an empty array. Note that we use /// the () type here since we never have a non empty array. pub withdrawals: Option>, - /// Optional extension enabled in Ecotone and later, containing the block root of the parent beacon block. - pub parent_beacon_block_root: Option, /// The batch epoch number from derivation. This value is not expected by the engine is skipped /// during serialization and deserialization. #[serde(skip)] diff --git a/src/l1/l1_info.rs b/src/l1/l1_info.rs index de974f84..d7c5b352 100644 --- a/src/l1/l1_info.rs +++ b/src/l1/l1_info.rs @@ -31,6 +31,8 @@ pub struct L1BlockInfo { pub base_fee: U256, /// L1 mix hash (prevrandao) pub mix_hash: H256, + /// Post-Ecotone beacon block root + pub parent_beacon_block_root: Option, } impl TryFrom<&Block> for L1BlockInfo { @@ -52,12 +54,15 @@ impl TryFrom<&Block> for L1BlockInfo { let mix_hash = value.mix_hash.ok_or(eyre::eyre!("block not included"))?; + let parent_beacon_block_root = value.parent_beacon_block_root; + Ok(L1BlockInfo { number, hash, timestamp, base_fee, mix_hash, + parent_beacon_block_root, }) } } diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index 8be9bc6b..23a909b4 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -24,6 +24,14 @@ pub struct BlockHandler { blocks_v1_topic: IdentTopic, /// The libp2p topic for Canyon/Delta blocks: `/optimism/{chain_id}/1/blocks` blocks_v2_topic: IdentTopic, + blocks_v3_topic: IdentTopic, +} + +struct ExecutionPayloadEnvelope { + parent_beacon_block_root: Option, + payload: ExecutionPayload, + signature: Signature, + hash: PayloadHash, } impl Handler for BlockHandler { @@ -35,14 +43,16 @@ impl Handler for BlockHandler { decode_block_msg::(msg.data) } else if msg.topic == self.blocks_v2_topic.hash() { decode_block_msg::(msg.data) + } else if msg.topic == self.blocks_v3_topic.hash() { + decode_ecotone_block_msg(msg.data) } else { return MessageAcceptance::Reject; }; match decoded { - Ok((payload, signature, payload_hash)) => { - if self.block_valid(&payload, signature, payload_hash) { - _ = self.block_sender.send(payload); + Ok(envelope) => { + if self.block_valid(&envelope) { + _ = self.block_sender.send(envelope.payload); MessageAcceptance::Accept } else { tracing::warn!("invalid unsafe block"); @@ -76,6 +86,7 @@ impl BlockHandler { unsafe_signer_recv: unsafe_recv, blocks_v1_topic: IdentTopic::new(format!("/optimism/{}/0/blocks", chain_id)), blocks_v2_topic: IdentTopic::new(format!("/optimism/{}/1/blocks", chain_id)), + blocks_v3_topic: IdentTopic::new(format!("/optimism/{}/2/blocks", chain_id)), }; (handler, recv) @@ -84,31 +95,26 @@ impl BlockHandler { /// Determines if a block is valid. /// /// True if the block is less than 1 minute old, and correctly signed by the unsafe block signer. - fn block_valid( - &self, - payload: &ExecutionPayload, - sig: Signature, - payload_hash: PayloadHash, - ) -> bool { + fn block_valid(&self, envelope: &ExecutionPayloadEnvelope) -> bool { let current_timestamp = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs(); - let is_future = payload.timestamp.as_u64() > current_timestamp + 5; - let is_past = payload.timestamp.as_u64() < current_timestamp - 60; + let is_future = envelope.payload.timestamp.as_u64() > current_timestamp + 5; + let is_past = envelope.payload.timestamp.as_u64() < current_timestamp - 60; let time_valid = !(is_future || is_past); - let msg = payload_hash.signature_message(self.chain_id); + let msg = envelope.hash.signature_message(self.chain_id); let block_signer = *self.unsafe_signer_recv.borrow(); - let sig_valid = sig.verify(msg, block_signer).is_ok(); + let sig_valid = envelope.signature.verify(msg, block_signer).is_ok(); time_valid && sig_valid } } -/// Decodes a sequence of bytes to a tuple of ([ExecutionPayload], [Signature], [PayloadHash]) -fn decode_block_msg(data: Vec) -> Result<(ExecutionPayload, Signature, PayloadHash)> +/// Decodes a sequence of bytes to an [ExecutionPayloadEnvelope] +fn decode_block_msg(data: Vec) -> Result where T: SimpleSerialize, ExecutionPayload: From, @@ -123,9 +129,42 @@ where let payload: T = deserialize(block_data)?; let payload: ExecutionPayload = ExecutionPayload::from(payload); - let payload_hash = PayloadHash::from(block_data); + let hash = PayloadHash::from(block_data); + + Ok(ExecutionPayloadEnvelope { + parent_beacon_block_root: None, + signature, + payload, + hash, + }) +} + +/// The Ecotone V3 block topic encoding includes the parent beacon block root +/// as described in the [specs]. +/// +/// [specs]: https://specs.optimism.io/protocol/rollup-node-p2p.html#block-encoding +fn decode_ecotone_block_msg(data: Vec) -> Result { + let mut decoder = snap::raw::Decoder::new(); + let decompressed = decoder.decompress_vec(&data)?; + let sig_data = &decompressed[..65]; + let parent_beacon_block_root = &decompressed[65..97]; + let block_data = &decompressed[97..]; + + let signature = Signature::try_from(sig_data)?; + + let parent_beacon_block_root = Some(H256::from_slice(parent_beacon_block_root)); + + let payload: ExecutionPayloadV3SSZ = deserialize(block_data)?; + let payload = ExecutionPayload::from(payload); + + let hash = PayloadHash::from(block_data); - Ok((payload, signature, payload_hash)) + Ok(ExecutionPayloadEnvelope { + parent_beacon_block_root, + signature, + payload, + hash, + }) } /// Represents the Keccak256 hash of the block @@ -214,6 +253,8 @@ impl From for ExecutionPayload { block_hash: convert_hash(value.block_hash), transactions: convert_tx_list(value.transactions), withdrawals: None, + blob_gas_used: None, + excess_blob_gas: None, } } } @@ -286,6 +327,53 @@ impl From for ExecutionPayload { block_hash: convert_hash(value.block_hash), transactions: convert_tx_list(value.transactions), withdrawals: Some(Vec::new()), + blob_gas_used: None, + excess_blob_gas: None, + } + } +} + +#[derive(SimpleSerialize, Default)] +struct ExecutionPayloadV3SSZ { + pub parent_hash: Bytes32, + pub fee_recipient: VecAddress, + pub state_root: Bytes32, + pub receipts_root: Bytes32, + pub logs_bloom: Vector, + pub prev_randao: Bytes32, + pub block_number: u64, + pub gas_limit: u64, + pub gas_used: u64, + pub timestamp: u64, + pub extra_data: List, + pub base_fee_per_gas: U256, + pub block_hash: Bytes32, + pub transactions: List, + pub withdrawals: List, + pub blob_gas_used: u64, + pub excess_blob_gas: u64, +} + +impl From for ExecutionPayload { + fn from(value: ExecutionPayloadV3SSZ) -> Self { + Self { + parent_hash: convert_hash(value.parent_hash), + fee_recipient: convert_address(value.fee_recipient), + state_root: convert_hash(value.state_root), + receipts_root: convert_hash(value.receipts_root), + logs_bloom: convert_byte_vector(value.logs_bloom), + prev_randao: convert_hash(value.prev_randao), + block_number: value.block_number.into(), + gas_limit: value.gas_limit.into(), + gas_used: value.gas_used.into(), + timestamp: value.timestamp.into(), + extra_data: convert_byte_list(value.extra_data), + base_fee_per_gas: convert_uint(value.base_fee_per_gas), + block_hash: convert_hash(value.block_hash), + transactions: convert_tx_list(value.transactions), + withdrawals: Some(Vec::new()), + blob_gas_used: Some(value.blob_gas_used.into()), + excess_blob_gas: Some(value.excess_blob_gas.into()), } } } From d3c9c7290b26bc351f8ef03d5da678c467e261c8 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:03:21 +0100 Subject: [PATCH 11/23] chore: network handler cleanup --- src/engine/payload.rs | 2 ++ src/network/handlers/block_handler.rs | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/engine/payload.rs b/src/engine/payload.rs index e9bb762d..f969af61 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -43,8 +43,10 @@ pub struct ExecutionPayload { #[serde(skip_serializing_if = "Option::is_none")] pub withdrawals: Option>, /// None if not present (pre-Ecotone) + #[serde(skip_serializing_if = "Option::is_none")] pub blob_gas_used: Option, /// None if not present (pre-Ecotone) + #[serde(skip_serializing_if = "Option::is_none")] pub excess_blob_gas: Option, } diff --git a/src/network/handlers/block_handler.rs b/src/network/handlers/block_handler.rs index 23a909b4..54868c9d 100644 --- a/src/network/handlers/block_handler.rs +++ b/src/network/handlers/block_handler.rs @@ -28,10 +28,11 @@ pub struct BlockHandler { } struct ExecutionPayloadEnvelope { - parent_beacon_block_root: Option, payload: ExecutionPayload, signature: Signature, hash: PayloadHash, + #[allow(unused)] + parent_beacon_block_root: Option, } impl Handler for BlockHandler { @@ -40,11 +41,11 @@ impl Handler for BlockHandler { tracing::debug!("received block"); let decoded = if msg.topic == self.blocks_v1_topic.hash() { - decode_block_msg::(msg.data) + decode_pre_ecotone_block_msg::(msg.data) } else if msg.topic == self.blocks_v2_topic.hash() { - decode_block_msg::(msg.data) + decode_pre_ecotone_block_msg::(msg.data) } else if msg.topic == self.blocks_v3_topic.hash() { - decode_ecotone_block_msg(msg.data) + decode_post_ecotone_block_msg(msg.data) } else { return MessageAcceptance::Reject; }; @@ -73,7 +74,7 @@ impl Handler for BlockHandler { } impl BlockHandler { - /// Creates a new [BlockHandler] and opens a channel @todo + /// Creates a new [BlockHandler] and opens a channel pub fn new( chain_id: u64, unsafe_recv: watch::Receiver
, @@ -114,7 +115,7 @@ impl BlockHandler { } /// Decodes a sequence of bytes to an [ExecutionPayloadEnvelope] -fn decode_block_msg(data: Vec) -> Result +fn decode_pre_ecotone_block_msg(data: Vec) -> Result where T: SimpleSerialize, ExecutionPayload: From, @@ -139,11 +140,11 @@ where }) } -/// The Ecotone V3 block topic encoding includes the parent beacon block root -/// as described in the [specs]. +/// Decodes a sequence of bytes to an [ExecutionPayloadEnvelope]. The Ecotone V3 +/// block topic encoding includes the parent beacon block root as described in the [specs]. /// /// [specs]: https://specs.optimism.io/protocol/rollup-node-p2p.html#block-encoding -fn decode_ecotone_block_msg(data: Vec) -> Result { +fn decode_post_ecotone_block_msg(data: Vec) -> Result { let mut decoder = snap::raw::Decoder::new(); let decompressed = decoder.decompress_vec(&data)?; let sig_data = &decompressed[..65]; From bdcafaed92221c93ff79f9d06e19f692b31fac76 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:03:31 +0100 Subject: [PATCH 12/23] feat: ecotone mainnet time --- src/config/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/mod.rs b/src/config/mod.rs index e9b8b0f0..4a3ae8b5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -858,6 +858,7 @@ mod test { "regolith_time": 1, "canyon_time": 2, "delta_time": 3, + "ecotone_time": 4, "batch_inbox_address": "0xff00000000000000000000000000000000000000", "deposit_contract_address": "0x6900000000000000000000000000000000000001", "l1_system_config_address": "0x6900000000000000000000000000000000000009" @@ -906,6 +907,7 @@ mod test { assert_eq!(chain.regolith_time, 1); assert_eq!(chain.canyon_time, 2); assert_eq!(chain.delta_time, 3); + assert_eq!(chain.ecotone_time, 4); assert_eq!(chain.blocktime, 2); assert_eq!( chain.l2_to_l1_message_passer, From af2dbe8f57d9ed34a18e082ab7b4b073e3a1937e Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:44:32 +0100 Subject: [PATCH 13/23] feat: added documentation, cleanup after rebase --- src/common/attributes_deposited.rs | 28 ++++++++++++++++++++-------- src/common/mod.rs | 2 ++ src/config/mod.rs | 2 +- src/l1/blob_encoding.rs | 1 + src/l1/blob_fetcher.rs | 11 +++++++---- src/l1/config_updates.rs | 6 ++++++ src/l1/mod.rs | 7 +++++++ 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/common/attributes_deposited.rs b/src/common/attributes_deposited.rs index decabc34..726dc125 100644 --- a/src/common/attributes_deposited.rs +++ b/src/common/attributes_deposited.rs @@ -5,18 +5,29 @@ use ethers::{ use eyre::Result; use lazy_static::lazy_static; +/// Represents the attributes deposited transcation call #[derive(Debug)] pub struct AttributesDepositedCall { + /// block number pub number: u64, + /// block timestamp pub timestamp: u64, + /// base fee pub basefee: U256, + /// block hash pub hash: H256, + /// sequence number of the L2 block pub sequence_number: u64, + /// batcher hash (should contain an address) pub batcher_hash: H256, + /// L1 fee overhead pub fee_overhead: U256, + /// L1 fee scalar pub fee_scalar: U256, - pub blob_base_fee_scalar: u32, - pub blob_base_fee: U256, + /// Blob base fee scalar (after Ecotone) + pub blob_base_fee_scalar: Option, + /// Blob base fee (after Ecotone) + pub blob_base_fee: Option, } const L1_INFO_BEDROCK_LEN: usize = 4 + 32 * 8; @@ -104,8 +115,8 @@ impl AttributesDepositedCall { fee_scalar, // Ecotone fields are not present in Bedrock attributes deposited calls - blob_base_fee_scalar: 0, - blob_base_fee: U256::zero(), + blob_base_fee_scalar: None, + blob_base_fee: None, }) } @@ -143,7 +154,8 @@ impl AttributesDepositedCall { let fee_scalar = U256::from(fee_scalar); // up-casting for backwards compatibility cursor += 4; - let blob_base_fee_scalar = u32::from_be_bytes(calldata[cursor..cursor + 4].try_into()?); + let blob_base_fee_scalar = + Some(u32::from_be_bytes(calldata[cursor..cursor + 4].try_into()?)); cursor += 4; let sequence_number = u64::from_be_bytes(calldata[cursor..cursor + 8].try_into()?); @@ -158,7 +170,7 @@ impl AttributesDepositedCall { let basefee = U256::from_big_endian(&calldata[cursor..cursor + 32]); cursor += 32; - let blob_base_fee = U256::from_big_endian(&calldata[cursor..cursor + 32]); + let blob_base_fee = Some(U256::from_big_endian(&calldata[cursor..cursor + 32])); cursor += 32; let hash = H256::from_slice(&calldata[cursor..cursor + 32]); @@ -227,8 +239,8 @@ mod tests { ); let expected_block_number = 10519970; let expected_timestamp = 1707650412; - let expected_blob_base_fee_scalar = 862000; - let expected_blob_base_fee = U256::from(17683022066u64); + let expected_blob_base_fee_scalar = Some(862000); + let expected_blob_base_fee = Some(U256::from(17683022066u64)); // Act let call = AttributesDepositedCall::try_from_ecotone(Bytes::from_str(calldata)?); diff --git a/src/common/mod.rs b/src/common/mod.rs index 010d3477..04f67682 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -9,6 +9,8 @@ use figment::value::{Dict, Tag, Value}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use crate::engine::ExecutionPayload; + +/// Attributes deposited transaction helpers pub mod attributes_deposited; pub use attributes_deposited::AttributesDepositedCall; diff --git a/src/config/mod.rs b/src/config/mod.rs index 4a3ae8b5..61a7a28f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -105,7 +105,7 @@ pub struct CliConfig { /// The L1 RPC #[serde(skip_serializing_if = "Option::is_none")] pub l1_rpc_url: Option, - /// The L1 beacon client RPC + /// The L1 beacon chain RPC URL #[serde(skip_serializing_if = "Option::is_none")] pub l1_beacon_url: Option, /// The L2 execution client RPC diff --git a/src/l1/blob_encoding.rs b/src/l1/blob_encoding.rs index 992629a1..cd6f35ab 100644 --- a/src/l1/blob_encoding.rs +++ b/src/l1/blob_encoding.rs @@ -6,6 +6,7 @@ const ENCODING_VERSION: u8 = 0; const VERSION_OFFSET: usize = 1; const ROUNDS: usize = 1024; +/// Encodes a blob of data into a byte array pub fn decode_blob_data(blob: &[u8]) -> Result { let mut output = vec![0; MAX_BLOB_DATA_SIZE]; diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index fff18527..b09aa4a9 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -14,6 +14,8 @@ use crate::config::Config; 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. pub type BatcherTransactionData = Bytes; /// The blob fetcher is responsible for fetching blob data from the L1 beacon chain, @@ -29,19 +31,20 @@ pub struct BlobFetcher { seconds_per_slot: AtomicU64, } +/// A beacon chain blob sidecar object. +/// KZG commitment and proof fields are not used in the current implementation. #[derive(Debug, Deserialize)] pub struct BlobSidecar { + /// Blob index (transactions can have more than one blob) #[serde(deserialize_with = "deserialize_string_to_u64")] pub index: u64, + /// Blob data (not decoded) #[serde(deserialize_with = "deserialize_blob_bytes")] pub blob: Vec, - // kzg_commitment: String, - // kzg_proof: String, - // signed_block_header: Value, - // kzg_commitment_inclusion_proof: Vec, } impl BlobFetcher { + /// Create a new blob fetcher with the given config. pub fn new(config: Arc) -> Self { Self { config, diff --git a/src/l1/config_updates.rs b/src/l1/config_updates.rs index 54940b0b..89c86293 100644 --- a/src/l1/config_updates.rs +++ b/src/l1/config_updates.rs @@ -1,10 +1,16 @@ use ethers::types::{Address, Log, U256}; use eyre::Result; +/// Represents a system config update event +#[derive(Debug)] pub enum SystemConfigUpdate { + /// The batch sender address has been updated BatchSender(Address), + /// The fee overhead and scalar have been updated Fees(U256, U256), + /// The gas has been updated Gas(U256), + /// The unsafe block signer has been updated UnsafeBlockSigner(Address), } diff --git a/src/l1/mod.rs b/src/l1/mod.rs index 166e8749..2fb38c18 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -1,14 +1,21 @@ +/// Module reposnsible for listening to the L1 chain and monitoring for new +/// blocks and events. 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; +/// 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::{BatcherTransactionData, BlobFetcher, BlobSidecar}; +/// Helper module for decoding blob data pub mod blob_encoding; pub use blob_encoding::decode_blob_data; From 88f194ad02051e224d7386635751692af5b6588e Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 18 Feb 2024 23:21:11 +0100 Subject: [PATCH 14/23] fix: startup script env variable name --- docker/start-magi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/start-magi.sh b/docker/start-magi.sh index 8292d0ff..03d47439 100755 --- a/docker/start-magi.sh +++ b/docker/start-magi.sh @@ -18,7 +18,7 @@ then --network $NETWORK \ --jwt-secret $JWT_SECRET \ --l1-rpc-url $L1_RPC_URL \ - --l1-beacon-url $L1_BEACON_URL \ + --l1-beacon-url $L1_BEACON_RPC_URL \ --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ @@ -31,7 +31,7 @@ then --network $NETWORK \ --jwt-secret $JWT_SECRET \ --l1-rpc-url $L1_RPC_URL \ - --l1-beacon-url $L1_BEACON_URL \ + --l1-beacon-url $L1_BEACON_RPC_URL \ --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ From 74bbbf0da49d43f29626d214c5aa41d4a70c4f43 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Thu, 22 Feb 2024 00:27:08 +0100 Subject: [PATCH 15/23] chore: added test, set actions to stable toolchain --- .github/workflows/test.yml | 12 ++++---- src/driver/types.rs | 57 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index baa0ca2d..c63c4a55 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,7 @@ name: test on: push: branches: - - master + - master pull_request: env: @@ -18,7 +18,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: stable override: true - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 @@ -32,7 +32,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: stable override: true - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 @@ -46,7 +46,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: stable override: true - uses: Swatinem/rust-cache@v2 - uses: actions-rs/cargo@v1 @@ -61,7 +61,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: stable override: true components: rustfmt - uses: Swatinem/rust-cache@v2 @@ -77,7 +77,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: stable override: true components: clippy - uses: Swatinem/rust-cache@v2 diff --git a/src/driver/types.rs b/src/driver/types.rs index 3b916c8b..27dfead3 100644 --- a/src/driver/types.rs +++ b/src/driver/types.rs @@ -46,7 +46,7 @@ impl HeadInfo { let call = AttributesDepositedCall::try_from_bedrock(tx_calldata)?; Ok(Self { - l2_block_info: block.try_into()?, + l2_block_info: BlockInfo::try_from(block)?, l1_epoch: Epoch::from(&call), sequence_number: call.sequence_number, }) @@ -65,7 +65,7 @@ impl HeadInfo { let call = AttributesDepositedCall::try_from_ecotone(tx_calldata)?; Ok(Self { - l2_block_info: block.try_into()?, + l2_block_info: BlockInfo::try_from(block)?, l1_epoch: Epoch::from(&call), sequence_number: call.sequence_number, }) @@ -258,4 +258,57 @@ mod tests { Ok(()) } } + + mod head_info_ecotone { + use crate::driver::HeadInfo; + use std::str::FromStr; + + use ethers::{ + providers::{Middleware, Provider}, + types::H256, + }; + use eyre::Result; + + #[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 expected_l2_block_number = 21564471; + let expected_l2_block_timestamp = 1708557010; + + let expected_l1_epoch_hash = H256::from_str( + "0x231ac984a3fc58757efe373b0b5bff0589c0e67a969a6cbc56ec959739525b31", + )?; + let expected_l1_epoch_block_number = 10575507; + let expected_l1_epoch_timestamp = 1708556928; + + let l2_rpc = std::env::var("L2_TEST_RPC_URL")?; + let provider = Provider::try_from(l2_rpc)?; + + let l2_block = provider.get_block_with_txs(l2_block_hash).await?.unwrap(); + let head = HeadInfo::try_from_ecotone_block(l2_block)?; + + 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!(sequence_number, 4); + } + + Ok(()) + } + } } From 0b55aed26a231fd0a8102e87adb882e894ad5705 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sat, 24 Feb 2024 13:42:03 +0100 Subject: [PATCH 16/23] fix: is ecotone block fn --- docker/docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 964a6f92..8d1e89bf 100755 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -9,7 +9,7 @@ x-logging: &logging services: magi: - image: a16zcrypto/magi:latest + # image: a16zcrypto/magi:latest container_name: magi build: dockerfile: Dockerfile @@ -23,6 +23,8 @@ services: - op-geth env_file: - .env + environment: + - RUST_LOG=magi=debug ports: - 9200:9200 - "${RPC_PORT}:${RPC_PORT}" From d9e8b73c37be88080f34769f342957388dc147b8 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 25 Feb 2024 19:02:34 +0100 Subject: [PATCH 17/23] fix: sync tests --- bin/magi.rs | 8 +++++++- docker/start-magi.sh | 4 ++-- src/config/mod.rs | 29 ++++++++++++++++---------- src/derive/stages/attributes.rs | 6 +++--- src/derive/state.rs | 17 +++++++++------- src/driver/engine_driver.rs | 4 +--- src/driver/info.rs | 36 +++++++++++++++++++++++---------- src/driver/mod.rs | 3 ++- src/engine/api.rs | 6 +++--- src/engine/payload.rs | 2 +- src/l1/blob_fetcher.rs | 4 ++-- src/runner/mod.rs | 4 ---- 12 files changed, 74 insertions(+), 49 deletions(-) diff --git a/bin/magi.rs b/bin/magi.rs index dab1b9de..a1620251 100644 --- a/bin/magi.rs +++ b/bin/magi.rs @@ -15,7 +15,7 @@ use serde::Serialize; #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); - let sync_mode = cli.sync_mode.clone(); + let sync_mode = cli.sync_mode; let verbose = cli.verbose; let logs_dir = cli.logs_dir.clone(); let logs_rotation = cli.logs_rotation.clone(); @@ -25,6 +25,12 @@ async fn main() -> Result<()> { let _guards = telemetry::init(verbose, logs_dir, logs_rotation); metrics::init()?; + tracing::info!( + target: "magi", + "Starting Magi. sync mode={}, network={}", + sync_mode, config.chain.network + ); + let runner = Runner::from_config(config) .with_sync_mode(sync_mode) .with_checkpoint_hash(checkpoint_hash); diff --git a/docker/start-magi.sh b/docker/start-magi.sh index 03d47439..4daf3595 100755 --- a/docker/start-magi.sh +++ b/docker/start-magi.sh @@ -19,8 +19,8 @@ then --jwt-secret $JWT_SECRET \ --l1-rpc-url $L1_RPC_URL \ --l1-beacon-url $L1_BEACON_RPC_URL \ - --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ - --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ + --l2-rpc-url http://${EXECUTION_CLIENT}:8565 \ + --l2-engine-url http://${EXECUTION_CLIENT}:8561 \ --rpc-port $RPC_PORT \ --rpc-addr $RPC_ADDR \ $DEVNET \ diff --git a/src/config/mod.rs b/src/config/mod.rs index 61a7a28f..44d75c9f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,4 +1,4 @@ -use std::{iter, path::PathBuf, process::exit, str::FromStr}; +use std::{fmt, iter, path::PathBuf, process::exit, str::FromStr}; use ethers::types::{Address, H256, U256}; use figment::{ @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; use crate::common::{BlockInfo, Epoch}; /// Sync Mode Specifies how `magi` should sync the L2 chain -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] pub enum SyncMode { /// Fast sync mode Fast, @@ -36,6 +36,17 @@ impl FromStr for SyncMode { } } +impl fmt::Display for SyncMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Fast => write!(f, "fast"), + Self::Checkpoint => write!(f, "checkpoint"), + Self::Challenge => write!(f, "challenge"), + Self::Full => write!(f, "full"), + } + } +} + /// The global `Magi` configuration. #[derive(Debug, Clone, Deserialize, Default)] pub struct Config { @@ -281,20 +292,16 @@ impl ChainConfig { } /// Returns true if the block is the first block subject to the Ecotone hardfork - pub fn is_ecotone_activation_block(&self, block_time: u64) -> bool { - if block_time < self.blocktime { - return false; - } - - block_time - self.blocktime < self.ecotone_time + 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, block_time: u64) -> bool { - let is_ecotone = block_time >= self.ecotone_time; + 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(block_time) + is_ecotone && !self.is_ecotone_activation_block(l2_block_timestamp) } /// [ChainConfig] for Optimism diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 75e6f6eb..c05b6095 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -73,8 +73,8 @@ impl Attributes { /// /// Calls `derive_transactions` to generate the raw transactions fn derive_attributes(&mut self, input: BlockInput) -> PayloadAttributes { - tracing::debug!("attributes derived from block {}", input.epoch.number); - tracing::debug!("batch epoch hash {:?}", input.epoch.hash); + tracing::debug!("deriving attributes from block: {}", input.epoch.number); + tracing::debug!("batch epoch hash: {:?}", input.epoch.hash); self.update_sequence_number(input.epoch.hash); @@ -137,9 +137,9 @@ impl Attributes { .chain .is_ecotone_activation_block(input.timestamp) { + tracing::debug!("found Ecotone activation block; Upgrade transactions added"); let mut ecotone_upgrade_txs = get_ecotone_upgrade_transactions(); transactions.append(&mut ecotone_upgrade_txs); - tracing::debug!("found Ecotone activation block; Upgrade transactions added"); } // Remaining transactions diff --git a/src/derive/state.rs b/src/derive/state.rs index 6db1f092..46e5068a 100644 --- a/src/derive/state.rs +++ b/src/derive/state.rs @@ -175,13 +175,16 @@ async fn l2_refs( for i in start..=head_num { let l2_block = provider.get_block_with_txs(i).await; if let Ok(Some(l2_block)) = l2_block { - if let Ok(head_info) = HeadInfo::try_from_l2_block(config, l2_block) { - refs.insert( - head_info.l2_block_info.number, - (head_info.l2_block_info, head_info.l1_epoch), - ); - } else { - tracing::warn!("could not get head info for L2 block {}", i); + match HeadInfo::try_from_l2_block(config, l2_block) { + Ok(head_info) => { + refs.insert( + head_info.l2_block_info.number, + (head_info.l2_block_info, head_info.l1_epoch), + ); + } + Err(e) => { + tracing::warn!(err = ?e, "could not get head info for L2 block {}", i); + } } } } diff --git a/src/driver/engine_driver.rs b/src/driver/engine_driver.rs index a58b44ec..9f577feb 100644 --- a/src/driver/engine_driver.rs +++ b/src/driver/engine_driver.rs @@ -224,9 +224,6 @@ fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Re attributes.timestamp ); - tracing::debug!("block: {:?}", block); - tracing::debug!("attributes: {:?}", attributes); - let attributes_hashes = attributes .transactions .as_ref() @@ -242,6 +239,7 @@ fn should_skip(block: &Block, attributes: &PayloadAttributes) -> Re .collect::>(); tracing::debug!("attribute hashes: {:?}", attributes_hashes); + tracing::debug!("block hashes: {:?}", block_hashes); let is_same = attributes_hashes == block_hashes && attributes.timestamp.as_u64() == block.timestamp.as_u64() diff --git a/src/driver/info.rs b/src/driver/info.rs index cecf9e37..678c0312 100644 --- a/src/driver/info.rs +++ b/src/driver/info.rs @@ -44,19 +44,33 @@ pub struct HeadInfoQuery {} impl HeadInfoQuery { /// Fetches the latest finalized L2 block pub async fn get_head_info(p: &P, config: &Config) -> HeadInfo { - p.get_block_with_txs(BlockId::Number(BlockNumber::Finalized)) + let parsed_head_info = match p + .get_block_with_txs(BlockId::Number(BlockNumber::Finalized)) .await - .ok() - .flatten() - .and_then(|l2_block| HeadInfo::try_from_l2_block(config, l2_block).ok()) - .unwrap_or_else(|| { - tracing::warn!("could not get head info. Falling back to the genesis head."); - HeadInfo { - l2_block_info: config.chain.l2_genesis, - l1_epoch: config.chain.l1_start_epoch, - sequence_number: 0, + { + Ok(Some(block)) => match HeadInfo::try_from_l2_block(config, block) { + Ok(head_info) => Some(head_info), + Err(e) => { + tracing::debug!(err = ?e, "could not parse L2 block into head info"); + None } - }) + }, + e => { + tracing::debug!("could not get finalied L2 block: {:?}", e); + None + } + }; + + if let Some(head_info) = parsed_head_info { + head_info + } else { + tracing::warn!("could not get head info. Falling back to the genesis head."); + HeadInfo { + l2_block_info: config.chain.l2_genesis, + l1_epoch: config.chain.l1_start_epoch, + sequence_number: 0, + } + } } } diff --git a/src/driver/mod.rs b/src/driver/mod.rs index cc4d3f5d..49935879 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -195,7 +195,8 @@ impl Driver { self.engine_driver .handle_attributes(next_attributes) - .await?; + .await + .map_err(|e| eyre::eyre!("failed to handle attributes: {}", e))?; tracing::info!( "safe head updated: {} {:?}", diff --git a/src/engine/api.rs b/src/engine/api.rs index b88c8ef1..3bdf56ba 100644 --- a/src/engine/api.rs +++ b/src/engine/api.rs @@ -121,8 +121,8 @@ impl EngineApi { body.insert("method".to_string(), Value::String(method.to_string())); body.insert("params".to_string(), Value::Array(params)); - tracing::debug!("Sending request to url: {:?}", self.base_url); - tracing::debug!("Sending request: {:?}", serde_json::to_string(&body)); + tracing::trace!("Sending request to url: {:?}", self.base_url); + tracing::trace!("Sending request: {:?}", serde_json::to_string(&body)); // Send the client request let client = self @@ -166,7 +166,7 @@ impl EngineApi { } if let Some(err) = res.error { - eyre::bail!(err.message); + eyre::bail!("Engine API POST error: {}", err.message); } // This scenario shouldn't occur as the response should always have either data or an error diff --git a/src/engine/payload.rs b/src/engine/payload.rs index f969af61..28097fc3 100644 --- a/src/engine/payload.rs +++ b/src/engine/payload.rs @@ -177,7 +177,7 @@ mod tests { #[tokio::test] async fn test_from_block_hash_to_execution_paylaod() -> Result<()> { - if std::env::var("L1_TEST_RPC_URL").is_ok() && std::env::var("L2_TEST_RPC_URL").is_ok() { + if std::env::var("L2_TEST_RPC_URL").is_ok() { let checkpoint_hash: H256 = "0xc2794a16acacd9f7670379ffd12b6968ff98e2a602f57d7d1f880220aa5a4973".parse()?; diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index b09aa4a9..b0aa59ea 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -99,8 +99,9 @@ impl BlobFetcher { let slot = self.get_slot_from_time(block.timestamp.as_u64()).await?; // perf: fetch only the required indexes instead of all let blobs = self.fetch_blob_sidecars(slot).await?; + tracing::debug!("fetched {} blobs for slot {}", blobs.len(), slot); - for (blob_index, blob_hash) in indexed_blobs { + for (blob_index, _) in indexed_blobs { 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. @@ -109,7 +110,6 @@ impl BlobFetcher { // decode the full blob let decoded_blob_data = decode_blob_data(&blob_sidecar.blob)?; - tracing::debug!("successfully decoded blob data for hash {:?}", blob_hash); batcher_transactions_data.push(decoded_blob_data); } diff --git a/src/runner/mod.rs b/src/runner/mod.rs index e574e08e..b5304df1 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -91,8 +91,6 @@ impl Runner { /// Syncs via L1 block derivation from the latest finalized block the execution client has synced to. /// Otherwise syncs from genesis pub async fn full_sync(&self) -> Result<()> { - tracing::info!("starting full sync"); - self.start_driver().await?; Ok(()) } @@ -102,8 +100,6 @@ 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<()> { - tracing::info!("starting checkpoint sync"); - let l2_provider = Provider::try_from(&self.config.l2_rpc_url)?; let checkpoint_sync_url = Provider::try_from(self.config.checkpoint_sync_url.as_ref().ok_or(eyre::eyre!( From e1d78d1ea49ba3b215f28c60990907e67886ee6c Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 25 Feb 2024 19:20:19 +0100 Subject: [PATCH 18/23] chore: minor cleanup --- docker/docker-compose.yml | 2 -- docker/start-magi.sh | 4 ++-- src/derive/stages/attributes.rs | 2 +- src/l1/blob_fetcher.rs | 13 ++++++++++++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 8d1e89bf..2b63ac63 100755 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -23,8 +23,6 @@ services: - op-geth env_file: - .env - environment: - - RUST_LOG=magi=debug ports: - 9200:9200 - "${RPC_PORT}:${RPC_PORT}" diff --git a/docker/start-magi.sh b/docker/start-magi.sh index 4daf3595..03d47439 100755 --- a/docker/start-magi.sh +++ b/docker/start-magi.sh @@ -19,8 +19,8 @@ then --jwt-secret $JWT_SECRET \ --l1-rpc-url $L1_RPC_URL \ --l1-beacon-url $L1_BEACON_RPC_URL \ - --l2-rpc-url http://${EXECUTION_CLIENT}:8565 \ - --l2-engine-url http://${EXECUTION_CLIENT}:8561 \ + --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ + --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ --rpc-addr $RPC_ADDR \ $DEVNET \ diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index c05b6095..2ca8f978 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -137,7 +137,7 @@ impl Attributes { .chain .is_ecotone_activation_block(input.timestamp) { - tracing::debug!("found Ecotone activation block; Upgrade transactions added"); + tracing::info!("found Ecotone activation block; Upgrade transactions added"); let mut ecotone_upgrade_txs = get_ecotone_upgrade_transactions(); transactions.append(&mut ecotone_upgrade_txs); } diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index b0aa59ea..aea8ffbe 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -12,6 +12,8 @@ use serde_json::Value; use super::decode_blob_data; use crate::config::Config; +/// The transaction type used to identify transactions that carry blobs +/// according to EIP 4844. const BLOB_CARRYING_TRANSACTION_TYPE: u64 = 3; /// The data contained in a batcher transaction. @@ -117,6 +119,7 @@ impl BlobFetcher { Ok(batcher_transactions_data) } + /// Check if a transaction was sent from the batch sender to the batch inbox. #[inline] fn is_valid_batcher_transaction(&self, tx: &Transaction) -> bool { let batch_sender = self.config.chain.system_config.batch_sender; @@ -125,7 +128,12 @@ impl BlobFetcher { tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false) } - #[inline] + /// Given a timestamp, return the slot number at which the timestamp + /// was included in the beacon chain. + /// + /// This method uses a cached genesis timestamp and seconds per slot + /// value to calculate the slot number. If the cache is empty, it fetches + /// the required data from the beacon RPC. async fn get_slot_from_time(&self, time: u64) -> Result { let mut genesis_timestamp = self.genesis_timestamp.load(Ordering::Relaxed); let mut seconds_per_slot = self.seconds_per_slot.load(Ordering::Relaxed); @@ -160,6 +168,7 @@ impl BlobFetcher { Ok((time - genesis_timestamp) / seconds_per_slot) } + /// Fetch the blob sidecars for a given slot. async fn fetch_blob_sidecars(&self, slot: u64) -> Result> { let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.config.l1_beacon_url); let full_url = format!("{}/{}", base_url, slot); @@ -173,6 +182,7 @@ impl BlobFetcher { Ok(blobs) } + /// Fetch the genesis timestamp from the beacon chain. async fn fetch_beacon_genesis_timestamp(&self) -> Result { let base_url = format!("{}/eth/v1/beacon/genesis", self.config.l1_beacon_url); @@ -187,6 +197,7 @@ impl BlobFetcher { Ok(genesis_time) } + /// Fetch the beacon chain spec. async fn fetch_beacon_spec(&self) -> Result { let base_url = format!("{}/eth/v1/config/spec", self.config.l1_beacon_url); From b99f40843ad440080df0e187a7443f9820ec8310 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sat, 2 Mar 2024 11:06:46 +0100 Subject: [PATCH 19/23] fix: rebase master and fix conflicts --- src/config/mod.rs | 1 + src/rpc/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/config/mod.rs b/src/config/mod.rs index 44d75c9f..c80a4fb5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -134,6 +134,7 @@ pub struct CliConfig { /// The port to serve the Magi RPC on. #[serde(skip_serializing_if = "Option::is_none")] pub rpc_port: Option, + /// The address to serve the Magi RPC on. #[serde(skip_serializing_if = "Option::is_none")] pub rpc_addr: Option, /// If Magi is running in devnet mode. diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 94e10c7a..ac71d057 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -182,6 +182,7 @@ mod tests { std::env::set_var("RUST_LOG", "trace"); let cli_config = CliConfig { l1_rpc_url: Some("".to_string()), + l1_beacon_url: None, l2_rpc_url: None, l2_engine_url: None, jwt_secret: Some("".to_string()), From d4f3fcf10a45236f5daf80af4b9067f8bc156354 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sat, 2 Mar 2024 12:54:24 +0100 Subject: [PATCH 20/23] fix: rpc test after rebasing --- src/rpc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index ac71d057..e340d67e 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -182,7 +182,7 @@ mod tests { std::env::set_var("RUST_LOG", "trace"); let cli_config = CliConfig { l1_rpc_url: Some("".to_string()), - l1_beacon_url: None, + l1_beacon_url: Some("".to_string()), l2_rpc_url: None, l2_engine_url: None, jwt_secret: Some("".to_string()), From 65869599703346b45a09e67802d36f0abefe250e Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:51:39 +0100 Subject: [PATCH 21/23] fix: annoying type conversion from ethers::Bytes --- src/l1/blob_fetcher.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index aea8ffbe..722f0ada 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -80,10 +80,7 @@ impl BlobFetcher { let tx_type = tx.transaction_type.map(|t| t.as_u64()).unwrap_or(0); if tx_type != BLOB_CARRYING_TRANSACTION_TYPE { - // this is necessary because ethers-rs wraps `bytes::Bytes` into its own type - // that doesn't come with free conversion back to `bytes::Bytes`. - let calldata = Bytes::from(tx.input.to_vec().clone()); - batcher_transactions_data.push(calldata); + batcher_transactions_data.push(tx.input.0.clone()); continue; } From 36dfac327591bab2720dc4261d68a396a0ea3802 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sat, 9 Mar 2024 11:46:04 +0100 Subject: [PATCH 22/23] feat: addressed code review --- src/derive/stages/attributes.rs | 2 +- src/l1/blob_fetcher.rs | 149 +++----------------------------- src/l1/chain_watcher.rs | 137 ++++++++++++++++++++++++++++- src/l1/l1_info.rs | 3 +- src/l1/mod.rs | 2 +- 5 files changed, 151 insertions(+), 142 deletions(-) diff --git a/src/derive/stages/attributes.rs b/src/derive/stages/attributes.rs index 2ca8f978..e7e95d05 100644 --- a/src/derive/stages/attributes.rs +++ b/src/derive/stages/attributes.rs @@ -131,7 +131,7 @@ impl Attributes { transactions.append(&mut user_deposited_txs); } - // Optional Ecotone upgrade transactions + // Ecotone upgrade transactions if self .config .chain diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index 722f0ada..b3955018 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -1,25 +1,9 @@ -use std::sync::{ - atomic::{AtomicU64, Ordering}, - Arc, -}; +use std::sync::atomic::{AtomicU64, Ordering}; -use bytes::Bytes; -use ethers::types::{Block, Transaction}; use eyre::Result; use serde::Deserialize; use serde_json::Value; -use super::decode_blob_data; -use crate::config::Config; - -/// The transaction type used to identify transactions that carry blobs -/// according to EIP 4844. -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. -pub type BatcherTransactionData = Bytes; - /// The blob fetcher is responsible for fetching blob data from the L1 beacon chain, /// along with relevant parsing and validation. /// @@ -27,7 +11,7 @@ pub type BatcherTransactionData = Bytes; /// included in the beacon chain is fetched on the first call to [`Self::get_slot_from_time`] /// and cached for all subsequent calls. pub struct BlobFetcher { - config: Arc, + l1_beacon_url: String, client: reqwest::Client, genesis_timestamp: AtomicU64, seconds_per_slot: AtomicU64, @@ -47,91 +31,22 @@ pub struct BlobSidecar { impl BlobFetcher { /// Create a new blob fetcher with the given config. - pub fn new(config: Arc) -> Self { + pub fn new(l1_beacon_url: String) -> Self { Self { - config, + l1_beacon_url, client: reqwest::Client::new(), genesis_timestamp: AtomicU64::new(0), seconds_per_slot: AtomicU64::new(0), } } - /// Given a block, return a list of `BatcherTransactionData` containing either the - /// calldata or the decoded blob data for each batcher transaction in the block. - pub async fn get_batcher_transactions( - &self, - block: &Block, - ) -> Result> { - let mut batcher_transactions_data = Vec::new(); - let mut indexed_blobs = Vec::new(); - let mut blob_index = 0; - - for tx in block.transactions.iter() { - let tx_blob_hashes: Vec = tx - .other - .get_deserialized("blobVersionedHashes") - .unwrap_or(Ok(Vec::new())) - .unwrap_or_default(); - - if !self.is_valid_batcher_transaction(tx) { - blob_index += tx_blob_hashes.len(); - continue; - } - - let tx_type = tx.transaction_type.map(|t| t.as_u64()).unwrap_or(0); - if tx_type != BLOB_CARRYING_TRANSACTION_TYPE { - batcher_transactions_data.push(tx.input.0.clone()); - continue; - } - - for blob_hash in tx_blob_hashes { - indexed_blobs.push((blob_index, blob_hash)); - blob_index += 1; - } - } - - // if at this point there are no blobs, return early - if indexed_blobs.is_empty() { - return Ok(batcher_transactions_data); - } - - let slot = self.get_slot_from_time(block.timestamp.as_u64()).await?; - // perf: fetch only the required indexes instead of all - let blobs = self.fetch_blob_sidecars(slot).await?; - tracing::debug!("fetched {} blobs for slot {}", blobs.len(), slot); - - for (blob_index, _) in indexed_blobs { - 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); - }; - - // decode the full blob - let decoded_blob_data = decode_blob_data(&blob_sidecar.blob)?; - - batcher_transactions_data.push(decoded_blob_data); - } - - Ok(batcher_transactions_data) - } - - /// Check if a transaction was sent from the batch sender to the batch inbox. - #[inline] - fn is_valid_batcher_transaction(&self, tx: &Transaction) -> bool { - let batch_sender = self.config.chain.system_config.batch_sender; - let batch_inbox = self.config.chain.batch_inbox; - - tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false) - } - /// Given a timestamp, return the slot number at which the timestamp /// was included in the beacon chain. /// /// This method uses a cached genesis timestamp and seconds per slot /// value to calculate the slot number. If the cache is empty, it fetches /// the required data from the beacon RPC. - async fn get_slot_from_time(&self, time: u64) -> Result { + pub async fn get_slot_from_time(&self, time: u64) -> Result { let mut genesis_timestamp = self.genesis_timestamp.load(Ordering::Relaxed); let mut seconds_per_slot = self.seconds_per_slot.load(Ordering::Relaxed); @@ -166,8 +81,8 @@ impl BlobFetcher { } /// Fetch the blob sidecars for a given slot. - async fn fetch_blob_sidecars(&self, slot: u64) -> Result> { - let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.config.l1_beacon_url); + pub async fn fetch_blob_sidecars(&self, slot: u64) -> Result> { + let base_url = format!("{}/eth/v1/beacon/blob_sidecars", self.l1_beacon_url); let full_url = format!("{}/{}", base_url, slot); let res = self.client.get(full_url).send().await?.error_for_status()?; @@ -180,8 +95,8 @@ impl BlobFetcher { } /// Fetch the genesis timestamp from the beacon chain. - async fn fetch_beacon_genesis_timestamp(&self) -> Result { - let base_url = format!("{}/eth/v1/beacon/genesis", self.config.l1_beacon_url); + pub async fn fetch_beacon_genesis_timestamp(&self) -> Result { + let base_url = format!("{}/eth/v1/beacon/genesis", self.l1_beacon_url); let res = self.client.get(base_url).send().await?.error_for_status()?; let res = serde_json::from_slice::(&res.bytes().await?)?; @@ -195,8 +110,8 @@ impl BlobFetcher { } /// Fetch the beacon chain spec. - async fn fetch_beacon_spec(&self) -> Result { - let base_url = format!("{}/eth/v1/config/spec", self.config.l1_beacon_url); + pub async fn fetch_beacon_spec(&self) -> Result { + let base_url = format!("{}/eth/v1/config/spec", self.l1_beacon_url); let res = self.client.get(base_url).send().await?.error_for_status()?; let res = serde_json::from_slice::(&res.bytes().await?)?; @@ -226,10 +141,8 @@ where #[cfg(test)] mod tests { - use ethers::providers::{Http, Middleware, Provider}; use super::*; - use crate::config::ChainConfig; // TODO: update with a test from mainnet after dencun is active #[tokio::test] @@ -239,48 +152,10 @@ mod tests { return; }; - let config = Arc::new(Config { - l1_beacon_url, - ..Default::default() - }); - let slot_number = 7576509; - let fetcher = BlobFetcher::new(config); + let fetcher = BlobFetcher::new(l1_beacon_url); let blobs = fetcher.fetch_blob_sidecars(slot_number).await.unwrap(); assert_eq!(blobs.len(), 6); } - - // TODO: update with a test from mainnet after dencun is active - // also, this test will be flaky as nodes start to purge old blobs - #[tokio::test] - async fn test_get_batcher_transactions() { - let Ok(l1_beacon_url) = std::env::var("L1_GOERLI_BEACON_RPC_URL") else { - println!("L1_GOERLI_BEACON_RPC_URL not set; skipping test"); - return; - }; - let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { - println!("L1_TEST_RPC_URL not set; skipping test"); - return; - }; - - let config = Arc::new(Config { - l1_beacon_url, - chain: ChainConfig::optimism_goerli(), - ..Default::default() - }); - - let l1_block_number = 10515928; - let l1_provider = Provider::::try_from(l1_rpc_url).unwrap(); - let l1_block = l1_provider - .get_block_with_txs(l1_block_number) - .await - .unwrap() - .unwrap(); - - let fetcher = BlobFetcher::new(config); - let batcher_transactions = fetcher.get_batcher_transactions(&l1_block).await.unwrap(); - - assert_eq!(batcher_transactions.len(), 1); - } } diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index 57717e49..bd9d9702 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -1,5 +1,6 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; +use bytes::Bytes; use ethers::{ providers::{Http, HttpRateLimitRetryPolicy, Middleware, Provider, RetryClient}, types::{Address, Block, BlockNumber, Filter, Transaction, H256, U256}, @@ -14,6 +15,7 @@ use crate::{ common::BlockInfo, config::{Config, SystemConfig}, derive::stages::attributes::UserDeposited, + l1::decode_blob_data, }; use super::{l1_info::L1BlockInfo, BlobFetcher, L1Info, SystemConfigUpdate}; @@ -27,6 +29,14 @@ static TRANSACTION_DEPOSITED_TOPIC: Lazy = Lazy::new(|| { )) }); +/// The transaction type used to identify transactions that carry blobs +/// according to EIP 4844. +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. +pub type BatcherTransactionData = Bytes; + /// Handles watching the L1 chain and monitoring for new blocks, deposits, /// and batcher transactions. The monitoring loop is spawned in a seperate /// task and communication happens via the internal channels. When ChainWatcher @@ -166,7 +176,7 @@ impl InnerWatcher { l2_start_block: u64, ) -> Self { let provider = generate_http_provider(&config.l1_rpc_url); - let blob_fetcher = Arc::new(BlobFetcher::new(Arc::clone(&config))); + let blob_fetcher = Arc::new(BlobFetcher::new(config.l1_beacon_url.clone())); let system_config = if l2_start_block == config.chain.l2_genesis.number { config.chain.system_config @@ -243,7 +253,7 @@ impl InnerWatcher { let block = self.get_block(self.current_block).await?; let user_deposits = self.get_deposits(self.current_block).await?; - let batcher_transactions = self.blob_fetcher.get_batcher_transactions(&block).await?; + let batcher_transactions = self.get_batcher_transactions(&block).await?; let finalized = self.current_block >= self.finalized_block; @@ -415,6 +425,79 @@ impl InnerWatcher { } } } + + /// Given a block, return a list of [`BatcherTransactionData`] containing either the + /// calldata or the decoded blob data for each batcher transaction in the block. + pub async fn get_batcher_transactions( + &self, + block: &Block, + ) -> Result> { + let mut batcher_transactions_data = Vec::new(); + let mut indexed_blobs = Vec::new(); + let mut blob_index = 0; + + for tx in block.transactions.iter() { + let tx_blob_hashes: Vec = tx + .other + .get_deserialized("blobVersionedHashes") + .unwrap_or(Ok(Vec::new())) + .unwrap_or_default(); + + if !self.is_valid_batcher_transaction(tx) { + blob_index += tx_blob_hashes.len(); + continue; + } + + let tx_type = tx.transaction_type.map(|t| t.as_u64()).unwrap_or(0); + if tx_type != BLOB_CARRYING_TRANSACTION_TYPE { + batcher_transactions_data.push(tx.input.0.clone()); + continue; + } + + for blob_hash in tx_blob_hashes { + indexed_blobs.push((blob_index, blob_hash)); + blob_index += 1; + } + } + + // if at this point there are no blobs, return early + if indexed_blobs.is_empty() { + return Ok(batcher_transactions_data); + } + + let slot = self + .blob_fetcher + .get_slot_from_time(block.timestamp.as_u64()) + .await?; + + // perf: fetch only the required indexes instead of all + let blobs = self.blob_fetcher.fetch_blob_sidecars(slot).await?; + tracing::debug!("fetched {} blobs for slot {}", blobs.len(), slot); + + for (blob_index, _) in indexed_blobs { + 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); + }; + + // decode the full blob + let decoded_blob_data = decode_blob_data(&blob_sidecar.blob)?; + + batcher_transactions_data.push(decoded_blob_data); + } + + Ok(batcher_transactions_data) + } + + /// Check if a transaction was sent from the batch sender to the batch inbox. + #[inline] + fn is_valid_batcher_transaction(&self, tx: &Transaction) -> bool { + let batch_sender = self.config.chain.system_config.batch_sender; + let batch_inbox = self.config.chain.batch_inbox; + + tx.from == batch_sender && tx.to.map(|to| to == batch_inbox).unwrap_or(false) + } } fn generate_http_provider(url: &str) -> Arc>> { @@ -453,3 +536,53 @@ fn start_watcher( Ok((handle, block_update_receiver)) } + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use ethers::providers::{Http, Middleware, Provider}; + use tokio::sync::mpsc; + + use crate::{ + config::{ChainConfig, Config}, + l1::chain_watcher::InnerWatcher, + }; + + // TODO: update with a test from mainnet after dencun is active + // also, this test will be flaky as nodes start to purge old blobs + #[tokio::test] + async fn test_get_batcher_transactions() { + let Ok(l1_beacon_url) = std::env::var("L1_GOERLI_BEACON_RPC_URL") else { + println!("L1_GOERLI_BEACON_RPC_URL not set; skipping test"); + return; + }; + let Ok(l1_rpc_url) = std::env::var("L1_TEST_RPC_URL") else { + println!("L1_TEST_RPC_URL not set; skipping test"); + return; + }; + + let config = Arc::new(Config { + l1_beacon_url, + chain: ChainConfig::optimism_goerli(), + ..Default::default() + }); + + let l1_block_number = 10515928; + let l1_provider = Provider::::try_from(l1_rpc_url).unwrap(); + let l1_block = l1_provider + .get_block_with_txs(l1_block_number) + .await + .unwrap() + .unwrap(); + + let watcher_inner = InnerWatcher::new(config, mpsc::channel(1).0, l1_block_number, 0).await; + + let batcher_transactions = watcher_inner + .get_batcher_transactions(&l1_block) + .await + .unwrap(); + + assert_eq!(batcher_transactions.len(), 1); + } +} diff --git a/src/l1/l1_info.rs b/src/l1/l1_info.rs index d7c5b352..d1bc6ffc 100644 --- a/src/l1/l1_info.rs +++ b/src/l1/l1_info.rs @@ -1,8 +1,9 @@ use ethers::types::{Block, Transaction, H256, U256}; -use super::BatcherTransactionData; use crate::{config::SystemConfig, derive::stages::attributes::UserDeposited}; +use super::chain_watcher::BatcherTransactionData; + /// Data tied to a specific L1 block #[derive(Debug)] pub struct L1Info { diff --git a/src/l1/mod.rs b/src/l1/mod.rs index 2fb38c18..c09eb707 100644 --- a/src/l1/mod.rs +++ b/src/l1/mod.rs @@ -14,7 +14,7 @@ pub use l1_info::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::{BatcherTransactionData, BlobFetcher, BlobSidecar}; +pub use blob_fetcher::{BlobFetcher, BlobSidecar}; /// Helper module for decoding blob data pub mod blob_encoding; From b6e8f9a86154009789470db7d22f5cb5df3513d6 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Sun, 10 Mar 2024 12:54:38 +0100 Subject: [PATCH 23/23] chore: uncommented docker image name --- docker/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 2b63ac63..964a6f92 100755 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -9,7 +9,7 @@ x-logging: &logging services: magi: - # image: a16zcrypto/magi:latest + image: a16zcrypto/magi:latest container_name: magi build: dockerfile: Dockerfile