reth_prune_types/
target.rs1use crate::{PruneMode, ReceiptsLogPruneConfig};
2use serde::{Deserialize, Deserializer, Serialize};
3
4pub const MINIMUM_PRUNING_DISTANCE: u64 = 32 * 2 + 10_000;
10
11#[derive(Debug, Clone, Default, Deserialize, Eq, PartialEq, Serialize)]
13#[serde(default)]
14pub struct PruneModes {
15 #[serde(skip_serializing_if = "Option::is_none")]
17 pub sender_recovery: Option<PruneMode>,
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub transaction_lookup: Option<PruneMode>,
21 #[serde(
24 skip_serializing_if = "Option::is_none",
25 deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<MINIMUM_PRUNING_DISTANCE, _>"
26 )]
27 pub receipts: Option<PruneMode>,
28 #[serde(
30 skip_serializing_if = "Option::is_none",
31 deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<MINIMUM_PRUNING_DISTANCE, _>"
32 )]
33 pub account_history: Option<PruneMode>,
34 #[serde(
36 skip_serializing_if = "Option::is_none",
37 deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<MINIMUM_PRUNING_DISTANCE, _>"
38 )]
39 pub storage_history: Option<PruneMode>,
40 pub receipts_log_filter: ReceiptsLogPruneConfig,
46}
47
48impl PruneModes {
49 pub fn none() -> Self {
51 Self::default()
52 }
53
54 pub fn all() -> Self {
56 Self {
57 sender_recovery: Some(PruneMode::Full),
58 transaction_lookup: Some(PruneMode::Full),
59 receipts: Some(PruneMode::Full),
60 account_history: Some(PruneMode::Full),
61 storage_history: Some(PruneMode::Full),
62 receipts_log_filter: Default::default(),
63 }
64 }
65
66 pub fn has_receipts_pruning(&self) -> bool {
68 self.receipts.is_some() || !self.receipts_log_filter.is_empty()
69 }
70
71 pub fn is_empty(&self) -> bool {
73 self == &Self::none()
74 }
75}
76
77fn deserialize_opt_prune_mode_with_min_blocks<'de, const MIN_BLOCKS: u64, D: Deserializer<'de>>(
86 deserializer: D,
87) -> Result<Option<PruneMode>, D::Error> {
88 let prune_mode = Option::<PruneMode>::deserialize(deserializer)?;
89
90 match prune_mode {
91 Some(PruneMode::Full) if MIN_BLOCKS > 0 => {
92 Err(serde::de::Error::invalid_value(
93 serde::de::Unexpected::Str("full"),
94 &format!("prune mode that leaves at least {MIN_BLOCKS} blocks in the database")
96 .as_str(),
97 ))
98 }
99 Some(PruneMode::Distance(distance)) if distance < MIN_BLOCKS => {
100 Err(serde::de::Error::invalid_value(
101 serde::de::Unexpected::Unsigned(distance),
102 &format!("prune mode that leaves at least {MIN_BLOCKS} blocks in the database")
104 .as_str(),
105 ))
106 }
107 _ => Ok(prune_mode),
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use assert_matches::assert_matches;
115 use serde::Deserialize;
116
117 #[test]
118 fn test_deserialize_opt_prune_mode_with_min_blocks() {
119 #[derive(Debug, Deserialize, PartialEq, Eq)]
120 struct V(
121 #[serde(deserialize_with = "deserialize_opt_prune_mode_with_min_blocks::<10, _>")]
122 Option<PruneMode>,
123 );
124
125 assert!(serde_json::from_str::<V>(r#"{"distance": 10}"#).is_ok());
126 assert_matches!(
127 serde_json::from_str::<V>(r#"{"distance": 9}"#),
128 Err(err) if err.to_string() == "invalid value: integer `9`, expected prune mode that leaves at least 10 blocks in the database"
129 );
130
131 assert_matches!(
132 serde_json::from_str::<V>(r#""full""#),
133 Err(err) if err.to_string() == "invalid value: string \"full\", expected prune mode that leaves at least 10 blocks in the database"
134 );
135 }
136}