diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 30cea0efe9b1..faadd6ffdf59 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -131,7 +131,9 @@ where let last_canonical_hashes = externals.fetch_latest_canonical_hashes(config.num_of_canonical_hashes() as usize)?; - let last_finalized_block_number = externals.fetch_latest_finalized_block_number()?; + // If we haven't written the finalized block, assume it's zero + let last_finalized_block_number = + externals.fetch_latest_finalized_block_number()?.unwrap_or_default(); Ok(Self { externals, diff --git a/crates/blockchain-tree/src/externals.rs b/crates/blockchain-tree/src/externals.rs index eaa19f9193bc..a903ae749629 100644 --- a/crates/blockchain-tree/src/externals.rs +++ b/crates/blockchain-tree/src/externals.rs @@ -85,7 +85,9 @@ impl TreeExternals { Ok(hashes) } - pub(crate) fn fetch_latest_finalized_block_number(&self) -> ProviderResult { + pub(crate) fn fetch_latest_finalized_block_number( + &self, + ) -> ProviderResult> { self.provider_factory.provider()?.last_finalized_block_number() } diff --git a/crates/chain-state/src/chain_info.rs b/crates/chain-state/src/chain_info.rs index c9ac52366b2a..341d85c8c26c 100644 --- a/crates/chain-state/src/chain_info.rs +++ b/crates/chain-state/src/chain_info.rs @@ -20,8 +20,8 @@ impl ChainInfoTracker { /// Create a new chain info container for the given canonical head and finalized header if it /// exists. pub fn new(head: SealedHeader, finalized: Option) -> Self { - let (finalized_block, _) = watch::channel(finalized.clone()); - let (safe_block, _) = watch::channel(finalized); + let (finalized_block, _) = watch::channel(finalized); + let (safe_block, _) = watch::channel(None); Self { inner: Arc::new(ChainInfoInner { @@ -88,14 +88,12 @@ impl ChainInfoTracker { } /// Returns the safe header of the chain. - #[allow(dead_code)] pub fn get_safe_num_hash(&self) -> Option { let h = self.inner.safe_block.borrow(); h.as_ref().map(|h| h.num_hash()) } /// Returns the finalized header of the chain. - #[allow(dead_code)] pub fn get_finalized_num_hash(&self) -> Option { let h = self.inner.finalized_block.borrow(); h.as_ref().map(|h| h.num_hash()) diff --git a/crates/cli/commands/src/stage/unwind.rs b/crates/cli/commands/src/stage/unwind.rs index 7659fdfc1501..f4150cd22ae7 100644 --- a/crates/cli/commands/src/stage/unwind.rs +++ b/crates/cli/commands/src/stage/unwind.rs @@ -96,7 +96,9 @@ impl Command { let last_saved_finalized_block_number = provider.last_finalized_block_number()?; let range_min = range.clone().min().ok_or(eyre::eyre!("Could not fetch lower range end"))?; - if range_min < last_saved_finalized_block_number { + if last_saved_finalized_block_number.is_none() || + Some(range_min) < last_saved_finalized_block_number + { provider.save_finalized_block_number(BlockNumber::from(range_min))?; } diff --git a/crates/stages/api/src/pipeline/mod.rs b/crates/stages/api/src/pipeline/mod.rs index 79578f942d70..b2cdbfa1acd6 100644 --- a/crates/stages/api/src/pipeline/mod.rs +++ b/crates/stages/api/src/pipeline/mod.rs @@ -336,7 +336,12 @@ where // update finalized block if needed let last_saved_finalized_block_number = provider_rw.last_finalized_block_number()?; - if checkpoint.block_number < last_saved_finalized_block_number { + + // If None, that means the finalized block is not written so we should + // always save in that case + if last_saved_finalized_block_number.is_none() || + Some(checkpoint.block_number) < last_saved_finalized_block_number + { provider_rw.save_finalized_block_number(BlockNumber::from( checkpoint.block_number, ))?; diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 633489359c93..80b877b3118f 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -83,8 +83,11 @@ where latest: SealedHeader, ) -> ProviderResult { let provider = database.provider()?; - let finalized_block_number = provider.last_finalized_block_number()?; - let finalized_header = provider.sealed_header(finalized_block_number)?; + let finalized_header = provider + .last_finalized_block_number()? + .map(|num| provider.sealed_header(num)) + .transpose()? + .flatten(); Ok(Self { database, canonical_in_memory_state: CanonicalInMemoryState::with_head(latest, finalized_header), diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 4c105e6f35a3..a2b181f2fc1b 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -3663,7 +3663,7 @@ impl StatsReader for DatabaseProvider { } impl FinalizedBlockReader for DatabaseProvider { - fn last_finalized_block_number(&self) -> ProviderResult { + fn last_finalized_block_number(&self) -> ProviderResult> { let mut finalized_blocks = self .tx .cursor_read::()? @@ -3671,10 +3671,8 @@ impl FinalizedBlockReader for DatabaseProvider { .take(1) .collect::, _>>()?; - let last_finalized_block_number = finalized_blocks - .pop_first() - .unwrap_or((tables::ChainStateKey::LastFinalizedBlock, 0_u64)); - Ok(last_finalized_block_number.1) + let last_finalized_block_number = finalized_blocks.pop_first().map(|pair| pair.1); + Ok(last_finalized_block_number) } } diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index f704eb15d8e8..8684e8e0da0d 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -121,8 +121,11 @@ where .header_by_number(best.best_number)? .ok_or(ProviderError::HeaderNotFound(best.best_number.into()))?; - let finalized_block_number = provider.last_finalized_block_number()?; - let finalized_header = provider.sealed_header(finalized_block_number)?; + let finalized_header = provider + .last_finalized_block_number()? + .map(|num| provider.sealed_header(num)) + .transpose()? + .flatten(); Ok(Self::with_blocks(database, tree, latest_header.seal(best.best_hash), finalized_header)) } diff --git a/crates/storage/provider/src/traits/finalized_block.rs b/crates/storage/provider/src/traits/finalized_block.rs index a5ac128ac178..4bf4da798044 100644 --- a/crates/storage/provider/src/traits/finalized_block.rs +++ b/crates/storage/provider/src/traits/finalized_block.rs @@ -4,7 +4,9 @@ use reth_primitives::BlockNumber; /// Functionality to read the last known finalized block from the database. pub trait FinalizedBlockReader: Send + Sync { /// Returns the last finalized block number. - fn last_finalized_block_number(&self) -> ProviderResult; + /// + /// If no finalized block has been written yet, this returns `None`. + fn last_finalized_block_number(&self) -> ProviderResult>; } /// Functionality to write the last known finalized block to the database.