fix(staged-sync): prevent StaticFileProducer from running with an unwinded target on legacy engine (#11717)

This commit is contained in:
joshieDo
2024-10-17 12:00:25 +09:00
committed by GitHub
parent 24287e8562
commit 1b97b1d942
3 changed files with 29 additions and 7 deletions

View File

@ -9,7 +9,8 @@ use futures::FutureExt;
use reth_errors::RethResult; use reth_errors::RethResult;
use reth_primitives::static_file::HighestStaticFiles; use reth_primitives::static_file::HighestStaticFiles;
use reth_provider::{ use reth_provider::{
BlockReader, DatabaseProviderFactory, StageCheckpointReader, StaticFileProviderFactory, BlockReader, ChainStateBlockReader, DatabaseProviderFactory, StageCheckpointReader,
StaticFileProviderFactory,
}; };
use reth_static_file::{StaticFileProducer, StaticFileProducerWithResult}; use reth_static_file::{StaticFileProducer, StaticFileProducerWithResult};
use reth_tasks::TaskSpawner; use reth_tasks::TaskSpawner;
@ -31,8 +32,9 @@ pub struct StaticFileHook<Provider> {
impl<Provider> StaticFileHook<Provider> impl<Provider> StaticFileHook<Provider>
where where
Provider: StaticFileProviderFactory Provider: StaticFileProviderFactory
+ DatabaseProviderFactory<Provider: StageCheckpointReader + BlockReader> + DatabaseProviderFactory<
+ 'static, Provider: StageCheckpointReader + BlockReader + ChainStateBlockReader,
> + 'static,
{ {
/// Create a new instance /// Create a new instance
pub fn new( pub fn new(
@ -104,6 +106,11 @@ where
return Ok(None) 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 = let targets =
locked_static_file_producer.get_static_file_targets(HighestStaticFiles { locked_static_file_producer.get_static_file_targets(HighestStaticFiles {
headers: Some(finalized_block_number), headers: Some(finalized_block_number),
@ -137,8 +144,9 @@ where
impl<Provider> EngineHook for StaticFileHook<Provider> impl<Provider> EngineHook for StaticFileHook<Provider>
where where
Provider: StaticFileProviderFactory Provider: StaticFileProviderFactory
+ DatabaseProviderFactory<Provider: StageCheckpointReader + BlockReader> + DatabaseProviderFactory<
+ 'static, Provider: StageCheckpointReader + BlockReader + ChainStateBlockReader,
> + 'static,
{ {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"StaticFile" "StaticFile"

View File

@ -276,6 +276,10 @@ impl<N: ProviderNodeTypes> Pipeline<N> {
// Unwind stages in reverse order of execution // Unwind stages in reverse order of execution
let unwind_pipeline = self.stages.iter_mut().rev(); 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()?; let mut provider_rw = self.provider_factory.database_provider_rw()?;
for stage in unwind_pipeline { for stage in unwind_pipeline {

View File

@ -5,8 +5,8 @@ use alloy_primitives::BlockNumber;
use parking_lot::Mutex; use parking_lot::Mutex;
use rayon::prelude::*; use rayon::prelude::*;
use reth_provider::{ use reth_provider::{
providers::StaticFileWriter, BlockReader, DBProvider, DatabaseProviderFactory, providers::StaticFileWriter, BlockReader, ChainStateBlockReader, DBProvider,
StageCheckpointReader, StaticFileProviderFactory, DatabaseProviderFactory, StageCheckpointReader, StaticFileProviderFactory,
}; };
use reth_prune_types::PruneModes; use reth_prune_types::PruneModes;
use reth_stages_types::StageId; use reth_stages_types::StageId;
@ -106,6 +106,16 @@ impl<Provider> StaticFileProducerInner<Provider> {
} }
} }
impl<Provider> StaticFileProducerInner<Provider>
where
Provider: StaticFileProviderFactory + DatabaseProviderFactory<Provider: ChainStateBlockReader>,
{
/// Returns the last finalized block number on disk.
pub fn last_finalized_block(&self) -> ProviderResult<Option<BlockNumber>> {
self.provider.database_provider_ro()?.last_finalized_block_number()
}
}
impl<Provider> StaticFileProducerInner<Provider> impl<Provider> StaticFileProducerInner<Provider>
where where
Provider: StaticFileProviderFactory Provider: StaticFileProviderFactory