From 1b97b1d942c671831bb81c0ccc53a9018c9febc5 Mon Sep 17 00:00:00 2001 From: joshieDo <93316087+joshieDo@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:00:25 +0900 Subject: [PATCH] fix(staged-sync): prevent `StaticFileProducer` from running with an unwinded target on legacy engine (#11717) --- .../beacon/src/engine/hooks/static_file.rs | 18 +++++++++++++----- crates/stages/api/src/pipeline/mod.rs | 4 ++++ .../static-file/src/static_file_producer.rs | 14 ++++++++++++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/crates/consensus/beacon/src/engine/hooks/static_file.rs b/crates/consensus/beacon/src/engine/hooks/static_file.rs index 8a5a28f95..89231ed55 100644 --- a/crates/consensus/beacon/src/engine/hooks/static_file.rs +++ b/crates/consensus/beacon/src/engine/hooks/static_file.rs @@ -9,7 +9,8 @@ use futures::FutureExt; use reth_errors::RethResult; use reth_primitives::static_file::HighestStaticFiles; use reth_provider::{ - BlockReader, DatabaseProviderFactory, StageCheckpointReader, StaticFileProviderFactory, + BlockReader, ChainStateBlockReader, DatabaseProviderFactory, StageCheckpointReader, + StaticFileProviderFactory, }; use reth_static_file::{StaticFileProducer, StaticFileProducerWithResult}; use reth_tasks::TaskSpawner; @@ -31,8 +32,9 @@ pub struct StaticFileHook { impl StaticFileHook where Provider: StaticFileProviderFactory - + DatabaseProviderFactory - + 'static, + + DatabaseProviderFactory< + Provider: StageCheckpointReader + BlockReader + ChainStateBlockReader, + > + 'static, { /// Create a new instance pub fn new( @@ -104,6 +106,11 @@ where return Ok(None) }; + let finalized_block_number = locked_static_file_producer + .last_finalized_block()? + .map(|on_disk| finalized_block_number.min(on_disk)) + .unwrap_or(finalized_block_number); + let targets = locked_static_file_producer.get_static_file_targets(HighestStaticFiles { headers: Some(finalized_block_number), @@ -137,8 +144,9 @@ where impl EngineHook for StaticFileHook where Provider: StaticFileProviderFactory - + DatabaseProviderFactory - + 'static, + + DatabaseProviderFactory< + Provider: StageCheckpointReader + BlockReader + ChainStateBlockReader, + > + 'static, { fn name(&self) -> &'static str { "StaticFile" diff --git a/crates/stages/api/src/pipeline/mod.rs b/crates/stages/api/src/pipeline/mod.rs index 1f6d9341a..14225a595 100644 --- a/crates/stages/api/src/pipeline/mod.rs +++ b/crates/stages/api/src/pipeline/mod.rs @@ -276,6 +276,10 @@ impl Pipeline { // Unwind stages in reverse order of execution let unwind_pipeline = self.stages.iter_mut().rev(); + // Legacy Engine: This prevents a race condition in which the `StaticFileProducer` could + // attempt to proceed with a finalized block which has been unwinded + let _locked_sf_producer = self.static_file_producer.lock(); + let mut provider_rw = self.provider_factory.database_provider_rw()?; for stage in unwind_pipeline { diff --git a/crates/static-file/static-file/src/static_file_producer.rs b/crates/static-file/static-file/src/static_file_producer.rs index 32565fd6d..2c442aedf 100644 --- a/crates/static-file/static-file/src/static_file_producer.rs +++ b/crates/static-file/static-file/src/static_file_producer.rs @@ -5,8 +5,8 @@ use alloy_primitives::BlockNumber; use parking_lot::Mutex; use rayon::prelude::*; use reth_provider::{ - providers::StaticFileWriter, BlockReader, DBProvider, DatabaseProviderFactory, - StageCheckpointReader, StaticFileProviderFactory, + providers::StaticFileWriter, BlockReader, ChainStateBlockReader, DBProvider, + DatabaseProviderFactory, StageCheckpointReader, StaticFileProviderFactory, }; use reth_prune_types::PruneModes; use reth_stages_types::StageId; @@ -106,6 +106,16 @@ impl StaticFileProducerInner { } } +impl StaticFileProducerInner +where + Provider: StaticFileProviderFactory + DatabaseProviderFactory, +{ + /// Returns the last finalized block number on disk. + pub fn last_finalized_block(&self) -> ProviderResult> { + self.provider.database_provider_ro()?.last_finalized_block_number() + } +} + impl StaticFileProducerInner where Provider: StaticFileProviderFactory