mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-29 17:18:08 -05:00
feat(prune): take PruneMode::Full into account when validating the config (#3810)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::{serde_helper::deserialize_opt_prune_mode_with_min_distance, BlockNumber, PruneMode};
|
||||
use crate::{serde_helper::deserialize_opt_prune_mode_with_min_blocks, BlockNumber, PruneMode};
|
||||
use paste::paste;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -15,7 +15,7 @@ pub struct PruneModes {
|
||||
/// Receipts pruning configuration.
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
deserialize_with = "deserialize_opt_prune_mode_with_min_distance::<64, _>"
|
||||
deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<64, _>"
|
||||
)]
|
||||
pub receipts: Option<PruneMode>,
|
||||
/// Account History pruning configuration.
|
||||
@@ -27,7 +27,7 @@ pub struct PruneModes {
|
||||
}
|
||||
|
||||
macro_rules! impl_prune_parts {
|
||||
($(($part:ident, $human_part:expr)),+) => {
|
||||
($(($part:ident, $human_part:expr, $min_blocks:expr)),+) => {
|
||||
$(
|
||||
paste! {
|
||||
#[doc = concat!(
|
||||
@@ -51,8 +51,12 @@ macro_rules! impl_prune_parts {
|
||||
$human_part,
|
||||
" pruning needs to be done, inclusive, according to the provided tip."
|
||||
)]
|
||||
pub fn [<prune_to_block_ $part>](&self, tip: BlockNumber) -> Option<(BlockNumber, PruneMode)> {
|
||||
self.$part.as_ref().map(|mode| (self.prune_to_block(mode, tip), *mode))
|
||||
pub fn [<prune_target_block_ $part>](&self, tip: BlockNumber) -> Option<(BlockNumber, PruneMode)> {
|
||||
self.$part.as_ref().and_then(|mode| {
|
||||
self.prune_target_block(mode, tip, $min_blocks).map(|block| {
|
||||
(block, *mode)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
)+
|
||||
@@ -90,20 +94,30 @@ impl PruneModes {
|
||||
}
|
||||
|
||||
/// Returns block up to which pruning needs to be done, inclusive, according to the provided
|
||||
/// prune mode and tip.
|
||||
pub fn prune_to_block(&self, mode: &PruneMode, tip: BlockNumber) -> BlockNumber {
|
||||
/// prune mode, tip block number and minimum number of blocks allowed to be pruned.
|
||||
pub fn prune_target_block(
|
||||
&self,
|
||||
mode: &PruneMode,
|
||||
tip: BlockNumber,
|
||||
min_blocks: Option<u64>,
|
||||
) -> Option<BlockNumber> {
|
||||
match mode {
|
||||
PruneMode::Full => tip,
|
||||
PruneMode::Distance(distance) => tip.saturating_sub(*distance),
|
||||
PruneMode::Before(n) => *n,
|
||||
PruneMode::Full if min_blocks.unwrap_or_default() == 0 => Some(tip),
|
||||
PruneMode::Distance(distance) if *distance >= min_blocks.unwrap_or_default() => {
|
||||
Some(tip.saturating_sub(*distance))
|
||||
}
|
||||
PruneMode::Before(n) if tip.saturating_sub(*n) >= min_blocks.unwrap_or_default() => {
|
||||
Some(*n)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl_prune_parts!(
|
||||
(sender_recovery, "Sender Recovery"),
|
||||
(transaction_lookup, "Transaction Lookup"),
|
||||
(receipts, "Receipts"),
|
||||
(account_history, "Account History"),
|
||||
(storage_history, "Storage History")
|
||||
(sender_recovery, "Sender Recovery", None),
|
||||
(transaction_lookup, "Transaction Lookup", None),
|
||||
(receipts, "Receipts", Some(64)),
|
||||
(account_history, "Account History", None),
|
||||
(storage_history, "Storage History", None)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ pub use jsonu256::*;
|
||||
|
||||
pub mod num;
|
||||
mod prune;
|
||||
pub use prune::deserialize_opt_prune_mode_with_min_distance;
|
||||
pub use prune::deserialize_opt_prune_mode_with_min_blocks;
|
||||
|
||||
/// serde functions for handling primitive `u64` as [U64](crate::U64)
|
||||
pub mod u64_hex {
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
use crate::PruneMode;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
/// Deserializes [`Option<PruneMode>`] and validates that the value contained in
|
||||
/// [PruneMode::Distance] (if any) is not less than the const generic parameter `MIN_DISTANCE`.
|
||||
pub fn deserialize_opt_prune_mode_with_min_distance<
|
||||
/// Deserializes [`Option<PruneMode>`] and validates that the value is not less than the const
|
||||
/// generic parameter `MIN_BLOCKS`. This parameter represents the number of blocks that needs to be
|
||||
/// left in database after the pruning.
|
||||
///
|
||||
/// 1. For [PruneMode::Full], it fails if `MIN_BLOCKS > 0`.
|
||||
/// 2. For [PruneMode::Distance(distance)], it fails if `distance < MIN_BLOCKS + 1`. `+ 1` is needed
|
||||
/// because `PruneMode::Distance(0)` means that we leave zero blocks from the latest, meaning we
|
||||
/// have one block in the database.
|
||||
pub fn deserialize_opt_prune_mode_with_min_blocks<
|
||||
'de,
|
||||
const MIN_DISTANCE: u64,
|
||||
const MIN_BLOCKS: u64,
|
||||
D: Deserializer<'de>,
|
||||
>(
|
||||
deserializer: D,
|
||||
@@ -13,11 +19,20 @@ pub fn deserialize_opt_prune_mode_with_min_distance<
|
||||
let prune_mode = Option::<PruneMode>::deserialize(deserializer)?;
|
||||
|
||||
match prune_mode {
|
||||
Some(PruneMode::Distance(distance)) if distance < MIN_DISTANCE => {
|
||||
Some(PruneMode::Full) if MIN_BLOCKS > 0 => {
|
||||
Err(serde::de::Error::invalid_value(
|
||||
serde::de::Unexpected::Str("full"),
|
||||
// This message should have "expected" wording
|
||||
&format!("prune mode that leaves at least {MIN_BLOCKS} blocks in the database")
|
||||
.as_str(),
|
||||
))
|
||||
}
|
||||
Some(PruneMode::Distance(distance)) if distance < MIN_BLOCKS => {
|
||||
Err(serde::de::Error::invalid_value(
|
||||
serde::de::Unexpected::Unsigned(distance),
|
||||
// This message should have "expected" wording, so we say "not less than"
|
||||
&format!("prune mode distance not less than {MIN_DISTANCE} blocks").as_str(),
|
||||
// This message should have "expected" wording
|
||||
&format!("prune mode that leaves at least {MIN_BLOCKS} blocks in the database")
|
||||
.as_str(),
|
||||
))
|
||||
}
|
||||
_ => Ok(prune_mode),
|
||||
@@ -31,11 +46,11 @@ mod test {
|
||||
use serde::Deserialize;
|
||||
|
||||
#[test]
|
||||
fn deserialize_opt_prune_mode_with_min_distance() {
|
||||
fn deserialize_opt_prune_mode_with_min_blocks() {
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||
struct V(
|
||||
#[serde(
|
||||
deserialize_with = "super::deserialize_opt_prune_mode_with_min_distance::<10, _>"
|
||||
deserialize_with = "super::deserialize_opt_prune_mode_with_min_blocks::<10, _>"
|
||||
)]
|
||||
Option<PruneMode>,
|
||||
);
|
||||
@@ -43,7 +58,12 @@ mod test {
|
||||
assert!(serde_json::from_str::<V>(r#"{"distance": 10}"#).is_ok());
|
||||
assert_matches!(
|
||||
serde_json::from_str::<V>(r#"{"distance": 9}"#),
|
||||
Err(err) if err.to_string() == "invalid value: integer `9`, expected prune mode distance not less than 10 blocks"
|
||||
Err(err) if err.to_string() == "invalid value: integer `9`, expected prune mode that leaves at least 10 blocks in the database"
|
||||
);
|
||||
|
||||
assert_matches!(
|
||||
serde_json::from_str::<V>(r#""full""#),
|
||||
Err(err) if err.to_string() == "invalid value: string \"full\", expected prune mode that leaves at least 10 blocks in the database"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,9 @@ impl<DB: Database> Pruner<DB> {
|
||||
pub fn run(&mut self, tip_block_number: BlockNumber) -> PrunerResult {
|
||||
let provider = self.provider_factory.provider_rw()?;
|
||||
|
||||
if let Some((to_block, prune_mode)) = self.modes.prune_to_block_receipts(tip_block_number) {
|
||||
if let Some((to_block, prune_mode)) =
|
||||
self.modes.prune_target_block_receipts(tip_block_number)
|
||||
{
|
||||
self.prune_receipts(&provider, to_block, prune_mode)?;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user