reth_prune_types/
target.rsuse crate::{PruneMode, ReceiptsLogPruneConfig};
use serde::{Deserialize, Deserializer, Serialize};
pub const MINIMUM_PRUNING_DISTANCE: u64 = 32 * 2 + 10_000;
#[derive(Debug, Clone, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(default)]
pub struct PruneModes {
#[serde(skip_serializing_if = "Option::is_none")]
pub sender_recovery: Option<PruneMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub transaction_lookup: Option<PruneMode>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<MINIMUM_PRUNING_DISTANCE, _>"
)]
pub receipts: Option<PruneMode>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<MINIMUM_PRUNING_DISTANCE, _>"
)]
pub account_history: Option<PruneMode>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<MINIMUM_PRUNING_DISTANCE, _>"
)]
pub storage_history: Option<PruneMode>,
pub receipts_log_filter: ReceiptsLogPruneConfig,
}
impl PruneModes {
pub fn none() -> Self {
Self::default()
}
pub fn all() -> Self {
Self {
sender_recovery: Some(PruneMode::Full),
transaction_lookup: Some(PruneMode::Full),
receipts: Some(PruneMode::Full),
account_history: Some(PruneMode::Full),
storage_history: Some(PruneMode::Full),
receipts_log_filter: Default::default(),
}
}
pub fn has_receipts_pruning(&self) -> bool {
self.receipts.is_some() || !self.receipts_log_filter.is_empty()
}
pub fn is_empty(&self) -> bool {
self == &Self::none()
}
}
fn deserialize_opt_prune_mode_with_min_blocks<'de, const MIN_BLOCKS: u64, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Option<PruneMode>, D::Error> {
let prune_mode = Option::<PruneMode>::deserialize(deserializer)?;
match prune_mode {
Some(PruneMode::Full) if MIN_BLOCKS > 0 => {
Err(serde::de::Error::invalid_value(
serde::de::Unexpected::Str("full"),
&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),
&format!("prune mode that leaves at least {MIN_BLOCKS} blocks in the database")
.as_str(),
))
}
_ => Ok(prune_mode),
}
}
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
use serde::Deserialize;
#[test]
fn test_deserialize_opt_prune_mode_with_min_blocks() {
#[derive(Debug, Deserialize, PartialEq, Eq)]
struct V(
#[serde(deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<10, _>")]
Option<PruneMode>,
);
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 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"
);
}
}