From 412051cf5ed526cd35ca685d0930712c5b161861 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Mon, 29 Apr 2024 20:54:51 +0200 Subject: [PATCH] fix: checkpoint sync sequence number check (#221) --- src/l1/blob_fetcher.rs | 21 ---------------- src/l1/chain_watcher.rs | 16 +++++++------ src/runner/mod.rs | 53 ++++++++++++++++++----------------------- 3 files changed, 32 insertions(+), 58 deletions(-) diff --git a/src/l1/blob_fetcher.rs b/src/l1/blob_fetcher.rs index b3955018..97e35224 100644 --- a/src/l1/blob_fetcher.rs +++ b/src/l1/blob_fetcher.rs @@ -138,24 +138,3 @@ where let bytes = hex::decode(s).map_err(serde::de::Error::custom)?; Ok(bytes) } - -#[cfg(test)] -mod tests { - - use super::*; - - // 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; - }; - - let slot_number = 7576509; - let fetcher = BlobFetcher::new(l1_beacon_url); - let blobs = fetcher.fetch_blob_sidecars(slot_number).await.unwrap(); - - assert_eq!(blobs.len(), 6); - } -} diff --git a/src/l1/chain_watcher.rs b/src/l1/chain_watcher.rs index bd9d9702..416d6e97 100644 --- a/src/l1/chain_watcher.rs +++ b/src/l1/chain_watcher.rs @@ -541,7 +541,10 @@ fn start_watcher( mod tests { use std::sync::Arc; - use ethers::providers::{Http, Middleware, Provider}; + use ethers::{ + providers::{Http, Middleware, Provider}, + types::{BlockId, BlockNumber}, + }; use tokio::sync::mpsc; use crate::{ @@ -549,8 +552,6 @@ mod tests { 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 { @@ -568,21 +569,22 @@ mod tests { ..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) + .get_block_with_txs(BlockId::Number(BlockNumber::Latest)) .await .unwrap() .unwrap(); - let watcher_inner = InnerWatcher::new(config, mpsc::channel(1).0, l1_block_number, 0).await; + let watcher_inner = InnerWatcher::new(config, mpsc::channel(1).0, 0, 0).await; let batcher_transactions = watcher_inner .get_batcher_transactions(&l1_block) .await .unwrap(); - assert_eq!(batcher_transactions.len(), 1); + batcher_transactions.iter().for_each(|tx| { + assert!(!tx.is_empty()); + }); } } diff --git a/src/runner/mod.rs b/src/runner/mod.rs index b5304df1..3e2164c0 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -1,8 +1,8 @@ use std::{process, time::Duration}; use ethers::{ - providers::{Http, Middleware, Provider}, - types::{BlockId, BlockNumber, H256}, + providers::{Middleware, Provider}, + types::{Block, BlockId, BlockNumber, Transaction, H256}, }; use eyre::Result; use tokio::{ @@ -11,8 +11,8 @@ use tokio::{ }; use crate::{ - config::{Config, SyncMode, SystemAccounts}, - driver::Driver, + config::{Config, SyncMode}, + driver::{Driver, HeadInfo}, engine::{Engine, EngineApi, ExecutionPayload, ForkchoiceState, Status}, }; @@ -112,7 +112,12 @@ impl Runner { .parse() .expect("invalid checkpoint block hash provided"); - match Self::is_epoch_boundary(block_hash, &checkpoint_sync_url).await? { + let l2_block = checkpoint_sync_url + .get_block_with_txs(block_hash) + .await? + .ok_or_else(|| eyre::eyre!("could not find block"))?; + + match is_epoch_boundary(l2_block, &self.config)? { true => checkpoint_sync_url .get_block_with_txs(block_hash) .await? @@ -127,7 +132,12 @@ impl Runner { tracing::info!("finding the latest epoch boundary to use as checkpoint"); let mut block_number = checkpoint_sync_url.get_block_number().await?; - while !Self::is_epoch_boundary(block_number, &checkpoint_sync_url).await? { + let l2_block = checkpoint_sync_url + .get_block_with_txs(block_number) + .await? + .ok_or_else(|| eyre::eyre!("could not find block"))?; + + while !is_epoch_boundary(l2_block.clone(), &self.config)? { self.check_shutdown()?; block_number -= 1.into(); } @@ -219,29 +229,12 @@ impl Runner { Ok(()) } +} - /// Returns `true` if the L2 block is the first in an epoch (sequence number 0) - async fn is_epoch_boundary + Send + Sync>( - block: T, - checkpoint_sync_url: &Provider, - ) -> Result { - let l2_block = checkpoint_sync_url - .get_block_with_txs(block) - .await? - .ok_or_else(|| eyre::eyre!("could not find block"))?; - - let sequence_number = &l2_block - .transactions - .iter() - .find(|tx| tx.to.unwrap() == SystemAccounts::default().attributes_predeploy) - .expect("could not find setL1BlockValues tx in the epoch boundary search") - .input - .clone() - .into_iter() - .skip(132) - .take(32) - .collect::>(); - - Ok(sequence_number == &[0; 32]) - } +/// Returns `true` if the L2 block is the first in an epoch (sequence number 0) +fn is_epoch_boundary(l2_block: Block, config: &Config) -> Result { + let head_info = HeadInfo::try_from_l2_block(config, l2_block)?; + let sequence_number = head_info.sequence_number; + + Ok(sequence_number == 0) }