refactor: unify logic for blocks removal (#12743)

Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
This commit is contained in:
Arsenii Kulikov
2024-11-21 23:47:33 +04:00
committed by GitHub
parent edeacbecfb
commit 0558235b98
9 changed files with 267 additions and 536 deletions

View File

@ -2,7 +2,7 @@
use crate::common::{AccessRights, CliNodeTypes, Environment, EnvironmentArgs};
use alloy_eips::BlockHashOrNumber;
use alloy_primitives::{BlockNumber, B256};
use alloy_primitives::B256;
use clap::{Parser, Subcommand};
use reth_beacon_consensus::EthBeaconConsensus;
use reth_chainspec::{EthChainSpec, EthereumHardforks};
@ -17,6 +17,7 @@ use reth_node_core::args::NetworkArgs;
use reth_provider::{
providers::ProviderNodeTypes, BlockExecutionWriter, BlockNumReader, ChainSpecProvider,
ChainStateBlockReader, ChainStateBlockWriter, ProviderFactory, StaticFileProviderFactory,
StorageLocation,
};
use reth_prune::PruneModes;
use reth_stages::{
@ -25,7 +26,7 @@ use reth_stages::{
ExecutionStageThresholds, Pipeline, StageSet,
};
use reth_static_file::StaticFileProducer;
use std::{ops::RangeInclusive, sync::Arc};
use std::sync::Arc;
use tokio::sync::watch;
use tracing::info;
@ -52,16 +53,13 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> Command<C>
pub async fn execute<N: CliNodeTypes<ChainSpec = C::ChainSpec>>(self) -> eyre::Result<()> {
let Environment { provider_factory, config, .. } = self.env.init::<N>(AccessRights::RW)?;
let range = self.command.unwind_range(provider_factory.clone())?;
if *range.start() == 0 {
eyre::bail!("Cannot unwind genesis block")
}
let target = self.command.unwind_target(provider_factory.clone())?;
let highest_static_file_block = provider_factory
.static_file_provider()
.get_highest_static_files()
.max()
.filter(|highest_static_file_block| highest_static_file_block >= range.start());
.filter(|highest_static_file_block| *highest_static_file_block > target);
// Execute a pipeline unwind if the start of the range overlaps the existing static
// files. If that's the case, then copy all available data from MDBX to static files, and
@ -75,9 +73,9 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> Command<C>
}
if let Some(highest_static_file_block) = highest_static_file_block {
info!(target: "reth::cli", ?range, ?highest_static_file_block, "Executing a pipeline unwind.");
info!(target: "reth::cli", ?target, ?highest_static_file_block, "Executing a pipeline unwind.");
} else {
info!(target: "reth::cli", ?range, "Executing a pipeline unwind.");
info!(target: "reth::cli", ?target, "Executing a pipeline unwind.");
}
// This will build an offline-only pipeline if the `offline` flag is enabled
@ -86,29 +84,25 @@ impl<C: ChainSpecParser<ChainSpec: EthChainSpec + EthereumHardforks>> Command<C>
// Move all applicable data from database to static files.
pipeline.move_to_static_files()?;
pipeline.unwind((*range.start()).saturating_sub(1), None)?;
pipeline.unwind(target, None)?;
} else {
info!(target: "reth::cli", ?range, "Executing a database unwind.");
info!(target: "reth::cli", ?target, "Executing a database unwind.");
let provider = provider_factory.provider_rw()?;
let _ = provider
.take_block_and_execution_range(range.clone())
provider
.remove_block_and_execution_above(target, StorageLocation::Both)
.map_err(|err| eyre::eyre!("Transaction error on unwind: {err}"))?;
// update finalized block if needed
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 last_saved_finalized_block_number.is_none() ||
Some(range_min) < last_saved_finalized_block_number
{
provider.save_finalized_block_number(BlockNumber::from(range_min))?;
if last_saved_finalized_block_number.is_none_or(|f| f > target) {
provider.save_finalized_block_number(target)?;
}
provider.commit()?;
}
info!(target: "reth::cli", range=?range.clone(), count=range.count(), "Unwound blocks");
info!(target: "reth::cli", ?target, "Unwound blocks");
Ok(())
}
@ -183,13 +177,11 @@ enum Subcommands {
}
impl Subcommands {
/// Returns the block range to unwind.
///
/// This returns an inclusive range: [target..=latest]
fn unwind_range<N: ProviderNodeTypes<DB = Arc<DatabaseEnv>>>(
/// Returns the block to unwind to. The returned block will stay in database.
fn unwind_target<N: ProviderNodeTypes<DB = Arc<DatabaseEnv>>>(
&self,
factory: ProviderFactory<N>,
) -> eyre::Result<RangeInclusive<u64>> {
) -> eyre::Result<u64> {
let provider = factory.provider()?;
let last = provider.last_block_number()?;
let target = match self {
@ -200,11 +192,11 @@ impl Subcommands {
BlockHashOrNumber::Number(num) => *num,
},
Self::NumBlocks { amount } => last.saturating_sub(*amount),
} + 1;
};
if target > last {
eyre::bail!("Target block number is higher than the latest block number")
}
Ok(target..=last)
Ok(target)
}
}