diff --git a/crates/node/core/src/args/mod.rs b/crates/node/core/src/args/mod.rs index 9351128570..f12fe7e322 100644 --- a/crates/node/core/src/args/mod.rs +++ b/crates/node/core/src/args/mod.rs @@ -54,7 +54,7 @@ pub use dev::DevArgs; /// PruneArgs for configuring the pruning and full node mod pruning; -pub use pruning::PruningArgs; +pub use pruning::{DefaultPruningValues, PruningArgs}; /// DatadirArgs for configuring data storage paths mod datadir_args; diff --git a/crates/node/core/src/args/pruning.rs b/crates/node/core/src/args/pruning.rs index 0bd6525372..24575a8ff7 100644 --- a/crates/node/core/src/args/pruning.rs +++ b/crates/node/core/src/args/pruning.rs @@ -6,7 +6,88 @@ use clap::{builder::RangedU64ValueParser, Args}; use reth_chainspec::EthereumHardforks; use reth_config::config::PruneConfig; use reth_prune_types::{PruneMode, PruneModes, ReceiptsLogPruneConfig, MINIMUM_PRUNING_DISTANCE}; -use std::{collections::BTreeMap, ops::Not}; +use std::{collections::BTreeMap, ops::Not, sync::OnceLock}; + +/// Global static pruning defaults +static PRUNING_DEFAULTS: OnceLock = OnceLock::new(); + +/// Default values for `--full` and `--minimal` pruning modes that can be customized. +/// +/// Global defaults can be set via [`DefaultPruningValues::try_init`]. +#[derive(Debug, Clone)] +pub struct DefaultPruningValues { + /// Prune modes for `--full` flag. + /// + /// Note: `bodies_history` is ignored when `full_bodies_history_use_pre_merge` is `true`. + pub full_prune_modes: PruneModes, + /// If `true`, `--full` will set `bodies_history` to prune everything before the merge block + /// (Paris hardfork). If `false`, uses `full_prune_modes.bodies_history` directly. + pub full_bodies_history_use_pre_merge: bool, + /// Prune modes for `--minimal` flag. + pub minimal_prune_modes: PruneModes, +} + +impl DefaultPruningValues { + /// Initialize the global pruning defaults with this configuration. + /// + /// Returns `Err(self)` if already initialized. + pub fn try_init(self) -> Result<(), Self> { + PRUNING_DEFAULTS.set(self) + } + + /// Get a reference to the global pruning defaults. + pub fn get_global() -> &'static Self { + PRUNING_DEFAULTS.get_or_init(Self::default) + } + + /// Set the prune modes for `--full` flag. + pub fn with_full_prune_modes(mut self, modes: PruneModes) -> Self { + self.full_prune_modes = modes; + self + } + + /// Set whether `--full` should use pre-merge pruning for bodies history. + /// + /// When `true` (default), bodies are pruned before the Paris hardfork block. + /// When `false`, uses `full_prune_modes.bodies_history` directly. + pub const fn with_full_bodies_history_use_pre_merge(mut self, use_pre_merge: bool) -> Self { + self.full_bodies_history_use_pre_merge = use_pre_merge; + self + } + + /// Set the prune modes for `--minimal` flag. + pub fn with_minimal_prune_modes(mut self, modes: PruneModes) -> Self { + self.minimal_prune_modes = modes; + self + } +} + +impl Default for DefaultPruningValues { + fn default() -> Self { + Self { + full_prune_modes: PruneModes { + sender_recovery: Some(PruneMode::Full), + transaction_lookup: None, + receipts: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), + account_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), + storage_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), + // This field is ignored when full_bodies_history_use_pre_merge is true + bodies_history: None, + receipts_log_filter: Default::default(), + }, + full_bodies_history_use_pre_merge: true, + minimal_prune_modes: PruneModes { + sender_recovery: Some(PruneMode::Full), + transaction_lookup: Some(PruneMode::Full), + receipts: Some(PruneMode::Full), + account_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), + storage_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), + bodies_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), + receipts_log_filter: Default::default(), + }, + } + } +} /// Parameters for pruning and full node #[derive(Debug, Clone, Args, PartialEq, Eq, Default)] @@ -128,36 +209,22 @@ impl PruningArgs { // If --full is set, use full node defaults. if self.full { - config = PruneConfig { - block_interval: config.block_interval, - segments: PruneModes { - sender_recovery: Some(PruneMode::Full), - transaction_lookup: None, - receipts: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), - account_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), - storage_history: Some(PruneMode::Distance(MINIMUM_PRUNING_DISTANCE)), - bodies_history: chain_spec - .ethereum_fork_activation(EthereumHardfork::Paris) - .block_number() - .map(PruneMode::Before), - receipts_log_filter: Default::default(), - }, + let defaults = DefaultPruningValues::get_global(); + let mut segments = defaults.full_prune_modes.clone(); + if defaults.full_bodies_history_use_pre_merge { + segments.bodies_history = chain_spec + .ethereum_fork_activation(EthereumHardfork::Paris) + .block_number() + .map(PruneMode::Before); } + config = PruneConfig { block_interval: config.block_interval, segments } } // If --minimal is set, use minimal storage mode with aggressive pruning. if self.minimal { config = PruneConfig { block_interval: config.block_interval, - segments: PruneModes { - sender_recovery: Some(PruneMode::Full), - transaction_lookup: Some(PruneMode::Full), - receipts: Some(PruneMode::Full), - account_history: Some(PruneMode::Distance(10064)), - storage_history: Some(PruneMode::Distance(10064)), - bodies_history: Some(PruneMode::Distance(10064)), - receipts_log_filter: Default::default(), - }, + segments: DefaultPruningValues::get_global().minimal_prune_modes.clone(), } }