diff --git a/Cargo.lock b/Cargo.lock index 49e1010b..6c43dd44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1055,6 +1055,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fastrand" version = "2.0.2" @@ -1468,6 +1478,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "2.2.6" @@ -1667,7 +1683,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-sol-types", - "anyhow", + "eyre", "op-alloy-consensus", "serde", "serde_json", diff --git a/crates/derive/src/online/alloy_providers.rs b/crates/derive/src/online/alloy_providers.rs index c4c7e1c8..243b9887 100644 --- a/crates/derive/src/online/alloy_providers.rs +++ b/crates/derive/src/online/alloy_providers.rs @@ -193,7 +193,9 @@ impl>> L2ChainProvider for AlloyL2ChainProvide } let payload = self.payload_by_number(number).await?; - let l2_block_info = payload.to_l2_block_ref(self.rollup_config.as_ref())?; + let Ok(l2_block_info) = payload.to_l2_block_ref(self.rollup_config.as_ref()) else { + anyhow::bail!("Failed to convert payload to L2 block info") + }; self.l2_block_info_by_number_cache.put(number, l2_block_info); Ok(l2_block_info) } @@ -226,6 +228,9 @@ impl>> L2ChainProvider for AlloyL2ChainProvide } let envelope = self.payload_by_number(number).await?; - envelope.to_system_config(&rollup_config) + match envelope.to_system_config(&rollup_config) { + Ok(system_config) => Ok(system_config), + Err(e) => anyhow::bail!("Failed to convert payload to system config: {:?}", e), + } } } diff --git a/crates/derive/src/stages/attributes_queue/builder.rs b/crates/derive/src/stages/attributes_queue/builder.rs index 4282671d..9e03c43d 100644 --- a/crates/derive/src/stages/attributes_queue/builder.rs +++ b/crates/derive/src/stages/attributes_queue/builder.rs @@ -88,7 +88,11 @@ where )); } let receipts = self.receipts_fetcher.receipts_by_hash(epoch.hash).await?; - sys_config.update_with_receipts(&receipts, &self.rollup_cfg, header.timestamp)?; + if let Err(e) = + sys_config.update_with_receipts(&receipts, &self.rollup_cfg, header.timestamp) + { + return Err(BuilderError::Custom(anyhow::anyhow!(e))); + } let deposits = derive_deposits(epoch.hash, receipts, self.rollup_cfg.deposit_contract_address) .await?; @@ -126,13 +130,16 @@ where } // Build and encode the L1 info transaction for the current payload. - let (_, l1_info_tx_envelope) = L1BlockInfoTx::try_new_with_deposit_tx( + let (_, l1_info_tx_envelope) = match L1BlockInfoTx::try_new_with_deposit_tx( &self.rollup_cfg, &sys_config, sequence_number, &l1_header, next_l2_time, - )?; + ) { + Ok(tx) => tx, + Err(e) => return Err(BuilderError::Custom(anyhow::anyhow!(e))), + }; let mut encoded_l1_info_tx = Vec::with_capacity(l1_info_tx_envelope.length()); l1_info_tx_envelope.encode(&mut encoded_l1_info_tx); diff --git a/crates/derive/src/stages/l1_traversal.rs b/crates/derive/src/stages/l1_traversal.rs index 65c97510..ac7813a2 100644 --- a/crates/derive/src/stages/l1_traversal.rs +++ b/crates/derive/src/stages/l1_traversal.rs @@ -101,7 +101,7 @@ impl OriginAdvancer for L1Traversal { &self.rollup_config, next_l1_origin.timestamp, ) { - return Err(StageError::SystemConfigUpdate(e)); + return Err(StageError::SystemConfigUpdate(anyhow::anyhow!(e))); } self.block = Some(next_l1_origin); diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 52a07c7b..ace5f78d 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -9,7 +9,7 @@ repository.workspace = true homepage.workspace = true [dependencies] -anyhow.workspace = true +eyre = "0.6" alloy-consensus.workspace = true alloy-rlp = { workspace = true, features = ["derive"] } alloy-primitives = { workspace = true, features = ["rlp"] } diff --git a/crates/primitives/src/block_info.rs b/crates/primitives/src/block_info.rs index 053f7117..9f7967df 100644 --- a/crates/primitives/src/block_info.rs +++ b/crates/primitives/src/block_info.rs @@ -4,7 +4,7 @@ use super::{BlockID, DepositSourceDomain, L1InfoDepositSource, RollupConfig, Sys use alloc::vec::Vec; use alloy_consensus::Header; use alloy_primitives::{address, Address, Bytes, TxKind, B256, U256}; -use anyhow::{anyhow, Result}; +use eyre::Result; use op_alloy_consensus::{OpTxEnvelope, TxDeposit}; /// The system transaction gas limit post-Regolith @@ -129,10 +129,10 @@ impl L1BlockInfoTx { let scalar = system_config.l1_fee_scalar.to_be_bytes::<32>(); let blob_base_fee_scalar = (scalar[0] == L1_SCALAR_ECOTONE) .then(|| { - Ok(u32::from_be_bytes( + Ok::(u32::from_be_bytes( scalar[24..28] .try_into() - .map_err(|_| anyhow!("Failed to parse L1 blob base fee scalar"))?, + .map_err(|_| eyre::eyre!("Failed to parse L1 blob base fee scalar"))?, )) }) .transpose()? @@ -140,7 +140,7 @@ impl L1BlockInfoTx { let base_fee_scalar = u32::from_be_bytes( scalar[28..32] .try_into() - .map_err(|_| anyhow!("Failed to parse base fee scalar"))?, + .map_err(|_| eyre::eyre!("Failed to parse base fee scalar"))?, ); Ok(Self::Ecotone(L1BlockInfoEcotone { number: l1_header.number, @@ -219,7 +219,7 @@ impl L1BlockInfoTx { L1_INFO_TX_SELECTOR_ECOTONE => { Ok(Self::Ecotone(L1BlockInfoEcotone::decode_calldata(r)?)) } - _ => anyhow::bail!("Unreachable case; Invalid L1 info transaction selector."), + _ => eyre::bail!("Unreachable case; Invalid L1 info transaction selector."), } } @@ -287,18 +287,19 @@ impl L1BlockInfoBedrock { /// Decodes the [L1BlockInfoBedrock] object from ethereum transaction calldata. pub fn decode_calldata(r: &[u8]) -> Result { if r.len() != L1_INFO_TX_LEN_BEDROCK { - anyhow::bail!("Invalid calldata length for Bedrock L1 info transaction"); + eyre::bail!("Invalid calldata length for Bedrock L1 info transaction"); } let number = - u64::from_be_bytes(r[28..36].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[28..36].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let time = - u64::from_be_bytes(r[60..68].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[60..68].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let base_fee = - u64::from_be_bytes(r[92..100].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[92..100].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let block_hash = B256::from_slice(r[100..132].as_ref()); - let sequence_number = - u64::from_be_bytes(r[156..164].try_into().map_err(|_| anyhow!("Conversion error"))?); + let sequence_number = u64::from_be_bytes( + r[156..164].try_into().map_err(|_| eyre::eyre!("Conversion error"))?, + ); let batcher_address = Address::from_slice(r[176..196].as_ref()); let l1_fee_overhead = U256::from_be_slice(r[196..228].as_ref()); let l1_fee_scalar = U256::from_be_slice(r[228..260].as_ref()); @@ -336,23 +337,24 @@ impl L1BlockInfoEcotone { /// Decodes the [L1BlockInfoEcotone] object from ethereum transaction calldata. pub fn decode_calldata(r: &[u8]) -> Result { if r.len() != L1_INFO_TX_LEN_ECOTONE { - anyhow::bail!("Invalid calldata length for Ecotone L1 info transaction"); + eyre::bail!("Invalid calldata length for Ecotone L1 info transaction"); } let base_fee_scalar = - u32::from_be_bytes(r[4..8].try_into().map_err(|_| anyhow!("Conversion error"))?); + u32::from_be_bytes(r[4..8].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let blob_base_fee_scalar = - u32::from_be_bytes(r[8..12].try_into().map_err(|_| anyhow!("Conversion error"))?); + u32::from_be_bytes(r[8..12].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let sequence_number = - u64::from_be_bytes(r[12..20].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[12..20].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let timestamp = - u64::from_be_bytes(r[20..28].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[20..28].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let l1_block_number = - u64::from_be_bytes(r[28..36].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[28..36].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); let base_fee = - u64::from_be_bytes(r[60..68].try_into().map_err(|_| anyhow!("Conversion error"))?); - let blob_base_fee = - u128::from_be_bytes(r[84..100].try_into().map_err(|_| anyhow!("Conversion error"))?); + u64::from_be_bytes(r[60..68].try_into().map_err(|_| eyre::eyre!("Conversion error"))?); + let blob_base_fee = u128::from_be_bytes( + r[84..100].try_into().map_err(|_| eyre::eyre!("Conversion error"))?, + ); let block_hash = B256::from_slice(r[100..132].as_ref()); let batcher_address = Address::from_slice(r[144..164].as_ref()); @@ -512,7 +514,7 @@ mod test { u32::from_be_bytes( scalar[24..28] .try_into() - .map_err(|_| anyhow!("Failed to parse L1 blob base fee scalar")) + .map_err(|_| eyre::eyre!("Failed to parse L1 blob base fee scalar")) .unwrap(), ) }) @@ -520,7 +522,7 @@ mod test { let base_fee_scalar = u32::from_be_bytes( scalar[28..32] .try_into() - .map_err(|_| anyhow!("Failed to parse base fee scalar")) + .map_err(|_| eyre::eyre!("Failed to parse base fee scalar")) .unwrap(), ); assert_eq!(l1_info.blob_base_fee_scalar, blob_base_fee_scalar); diff --git a/crates/primitives/src/deposits.rs b/crates/primitives/src/deposits.rs index 8c40dbd2..ad389331 100644 --- a/crates/primitives/src/deposits.rs +++ b/crates/primitives/src/deposits.rs @@ -54,8 +54,8 @@ pub enum DepositError { MintDecode(Bytes), /// Failed to decode the deposit gas value. GasDecode(Bytes), - /// A custom error wrapping [anyhow::Error]. - Custom(anyhow::Error), + /// A custom error wrapping [eyre::Error]. + Custom(eyre::Error), } impl PartialEq for DepositError { diff --git a/crates/primitives/src/payload.rs b/crates/primitives/src/payload.rs index bf730db4..661ed356 100644 --- a/crates/primitives/src/payload.rs +++ b/crates/primitives/src/payload.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; -use anyhow::Result; +use eyre::Result; use op_alloy_consensus::{OpTxEnvelope, OpTxType}; /// Fixed and variable memory costs for a payload. @@ -124,12 +124,12 @@ impl L2ExecutionPayloadEnvelope { rollup_config.genesis.l2.number { if execution_payload.block_hash != rollup_config.genesis.l2.hash { - anyhow::bail!("Invalid genesis hash"); + eyre::bail!("Invalid genesis hash"); } (rollup_config.genesis.l1, 0) } else { if execution_payload.transactions.is_empty() { - anyhow::bail!( + eyre::bail!( "L2 block is missing L1 info deposit transaction, block hash: {}", execution_payload.block_hash ); @@ -137,13 +137,13 @@ impl L2ExecutionPayloadEnvelope { let ty = execution_payload.transactions[0][0]; if ty != OpTxType::Deposit as u8 { - anyhow::bail!("First payload transaction has unexpected type: {:?}", ty); + eyre::bail!("First payload transaction has unexpected type: {:?}", ty); } let tx = OpTxEnvelope::decode(&mut execution_payload.transactions[0][1..].as_ref()) - .map_err(|e| anyhow::anyhow!(e))?; + .map_err(|e| eyre::eyre!(e))?; let OpTxEnvelope::Deposit(tx) = tx else { - anyhow::bail!("First payload transaction has unexpected type: {:?}", tx.tx_type()); + eyre::bail!("First payload transaction has unexpected type: {:?}", tx.tx_type()); }; let l1_info = L1BlockInfoTx::decode_calldata(tx.input.as_ref())?; @@ -168,26 +168,26 @@ impl L2ExecutionPayloadEnvelope { if execution_payload.block_number == rollup_config.genesis.l2.number { if execution_payload.block_hash != rollup_config.genesis.l2.hash { - anyhow::bail!("Invalid genesis hash"); + eyre::bail!("Invalid genesis hash"); } return Ok(rollup_config.genesis.system_config); } if execution_payload.transactions.is_empty() { - anyhow::bail!( + eyre::bail!( "L2 block is missing L1 info deposit transaction, block hash: {}", execution_payload.block_hash ); } let ty = execution_payload.transactions[0][0]; if ty != OpTxType::Deposit as u8 { - anyhow::bail!("First payload transaction has unexpected type: {:?}", ty); + eyre::bail!("First payload transaction has unexpected type: {:?}", ty); } let tx = OpTxEnvelope::decode(&mut execution_payload.transactions[0][1..].as_ref()) - .map_err(|e| anyhow::anyhow!(e))?; + .map_err(|e| eyre::eyre!(e))?; let OpTxEnvelope::Deposit(tx) = tx else { - anyhow::bail!("First payload transaction has unexpected type: {:?}", tx.tx_type()); + eyre::bail!("First payload transaction has unexpected type: {:?}", tx.tx_type()); }; let l1_info = L1BlockInfoTx::decode_calldata(tx.input.as_ref())?; diff --git a/crates/primitives/src/system_config.rs b/crates/primitives/src/system_config.rs index 13ba73ea..9dc3689b 100644 --- a/crates/primitives/src/system_config.rs +++ b/crates/primitives/src/system_config.rs @@ -7,7 +7,7 @@ use crate::{ use alloy_consensus::Receipt; use alloy_primitives::{address, Address, Log, U256}; use alloy_sol_types::{sol, SolType}; -use anyhow::{anyhow, bail, Result}; +use eyre::Result; /// Optimism system config contract values #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] @@ -41,7 +41,7 @@ pub enum SystemConfigUpdateType { } impl TryFrom for SystemConfigUpdateType { - type Error = anyhow::Error; + type Error = eyre::Error; fn try_from(value: u64) -> core::prelude::v1::Result { match value { @@ -49,7 +49,7 @@ impl TryFrom for SystemConfigUpdateType { 1 => Ok(SystemConfigUpdateType::GasConfig), 2 => Ok(SystemConfigUpdateType::GasLimit), 3 => Ok(SystemConfigUpdateType::UnsafeBlockSigner), - _ => bail!("Invalid SystemConfigUpdateType value: {}", value), + _ => eyre::bail!("Invalid SystemConfigUpdateType value: {}", value), } } } @@ -73,7 +73,12 @@ impl SystemConfig { !topics.is_empty() && topics[0] == CONFIG_UPDATE_TOPIC { - self.process_config_update_log(log, rollup_config, l1_time)?; + match self.process_config_update_log(log, rollup_config, l1_time) { + Ok(_) => {} + Err(e) => { + eyre::bail!("Failed to process config update log: {}", e); + } + } } Ok(()) })?; @@ -100,66 +105,66 @@ impl SystemConfig { l1_time: u64, ) -> Result<()> { if log.topics().len() < 3 { - bail!("Invalid config update log: not enough topics"); + eyre::bail!("Invalid config update log: not enough topics"); } if log.topics()[0] != CONFIG_UPDATE_TOPIC { - bail!("Invalid config update log: invalid topic"); + eyre::bail!("Invalid config update log: invalid topic"); } // Parse the config update log let version = log.topics()[1]; if version != CONFIG_UPDATE_EVENT_VERSION_0 { - bail!("Invalid config update log: unsupported version"); + eyre::bail!("Invalid config update log: unsupported version"); } let update_type = u64::from_be_bytes( log.topics()[2].as_slice()[24..] .try_into() - .map_err(|_| anyhow!("Failed to convert update type to u64"))?, + .map_err(|_| eyre::eyre!("Failed to convert update type to u64"))?, ); let log_data = log.data.data.as_ref(); match update_type.try_into()? { SystemConfigUpdateType::Batcher => { if log_data.len() != 96 { - bail!("Invalid config update log: invalid data length"); + eyre::bail!("Invalid config update log: invalid data length"); } let pointer = ::abi_decode(&log_data[0..32], true) - .map_err(|_| anyhow!("Failed to decode batcher update log"))?; + .map_err(|_| eyre::eyre!("Failed to decode batcher update log"))?; if pointer != 32 { - bail!("Invalid config update log: invalid data pointer"); + eyre::bail!("Invalid config update log: invalid data pointer"); } let length = ::abi_decode(&log_data[32..64], true) - .map_err(|_| anyhow!("Failed to decode batcher update log"))?; + .map_err(|_| eyre::eyre!("Failed to decode batcher update log"))?; if length != 32 { - bail!("Invalid config update log: invalid data length"); + eyre::bail!("Invalid config update log: invalid data length"); } let batcher_address = ::abi_decode(&log.data.data.as_ref()[64..], true) - .map_err(|_| anyhow!("Failed to decode batcher update log"))?; + .map_err(|_| eyre::eyre!("Failed to decode batcher update log"))?; self.batcher_addr = batcher_address; } SystemConfigUpdateType::GasConfig => { if log_data.len() != 128 { - bail!("Invalid config update log: invalid data length"); + eyre::bail!("Invalid config update log: invalid data length"); } let pointer = ::abi_decode(&log_data[0..32], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data pointer"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid data pointer"))?; if pointer != 32 { - bail!("Invalid config update log: invalid data pointer"); + eyre::bail!("Invalid config update log: invalid data pointer"); } let length = ::abi_decode(&log_data[32..64], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data length"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid data length"))?; if length != 64 { - bail!("Invalid config update log: invalid data length"); + eyre::bail!("Invalid config update log: invalid data length"); } let overhead = ::abi_decode(&log_data[64..96], true) - .map_err(|_| anyhow!("Invalid config update log: invalid overhead"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid overhead"))?; let scalar = ::abi_decode(&log_data[96..], true) - .map_err(|_| anyhow!("Invalid config update log: invalid scalar"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid scalar"))?; if rollup_config.is_ecotone_active(l1_time) { if RollupConfig::check_ecotone_l1_system_config_scalar(scalar.to_be_bytes()) @@ -180,22 +185,22 @@ impl SystemConfig { } SystemConfigUpdateType::GasLimit => { if log_data.len() != 96 { - bail!("Invalid config update log: invalid data length"); + eyre::bail!("Invalid config update log: invalid data length"); } let pointer = ::abi_decode(&log_data[0..32], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data pointer"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid data pointer"))?; if pointer != 32 { - bail!("Invalid config update log: invalid data pointer"); + eyre::bail!("Invalid config update log: invalid data pointer"); } let length = ::abi_decode(&log_data[32..64], true) - .map_err(|_| anyhow!("Invalid config update log: invalid data length"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid data length"))?; if length != 32 { - bail!("Invalid config update log: invalid data length"); + eyre::bail!("Invalid config update log: invalid data length"); } let gas_limit = ::abi_decode(&log_data[64..], true) - .map_err(|_| anyhow!("Invalid config update log: invalid gas limit"))?; + .map_err(|_| eyre::eyre!("Invalid config update log: invalid gas limit"))?; self.gas_limit = gas_limit; } SystemConfigUpdateType::UnsafeBlockSigner => {