reth_prune_types/
segment.rs

1#![allow(deprecated)] // necessary to all defining deprecated `PruneSegment` variants
2
3use crate::MINIMUM_PRUNING_DISTANCE;
4use derive_more::Display;
5use strum::{EnumIter, IntoEnumIterator};
6use thiserror::Error;
7
8/// Segment of the data that can be pruned.
9///
10/// VERY IMPORTANT NOTE: new variants must be added to the end of this enum, and old variants which
11/// are no longer used must not be removed from this enum. The variant index is encoded directly
12/// when writing to the `PruneCheckpoint` table, so changing the order here will corrupt the table.
13#[derive(Debug, Display, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, EnumIter)]
14#[cfg_attr(test, derive(arbitrary::Arbitrary))]
15#[cfg_attr(any(test, feature = "reth-codec"), derive(reth_codecs::Compact))]
16#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
17#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))]
18pub enum PruneSegment {
19    /// Prune segment responsible for the `TransactionSenders` table.
20    SenderRecovery,
21    /// Prune segment responsible for the `TransactionHashNumbers` table.
22    TransactionLookup,
23    /// Prune segment responsible for all rows in `Receipts` table.
24    Receipts,
25    /// Prune segment responsible for some rows in `Receipts` table filtered by logs.
26    ContractLogs,
27    /// Prune segment responsible for the `AccountChangeSets` and `AccountsHistory` tables.
28    AccountHistory,
29    /// Prune segment responsible for the `StorageChangeSets` and `StoragesHistory` tables.
30    StorageHistory,
31    #[deprecated = "Variant indexes cannot be changed"]
32    #[strum(disabled)]
33    /// Prune segment responsible for the `CanonicalHeaders`, `Headers` tables.
34    Headers,
35    #[deprecated = "Variant indexes cannot be changed"]
36    #[strum(disabled)]
37    /// Prune segment responsible for the `Transactions` table.
38    Transactions,
39    #[deprecated = "Variant indexes cannot be changed"]
40    #[strum(disabled)]
41    /// Prune segment responsible for all rows in `AccountsTrieChangeSets` and
42    /// `StoragesTrieChangeSets` table.
43    MerkleChangeSets,
44    /// Prune segment responsible for bodies (transactions in static files).
45    Bodies,
46}
47
48#[cfg(test)]
49#[allow(clippy::derivable_impls)]
50impl Default for PruneSegment {
51    fn default() -> Self {
52        Self::SenderRecovery
53    }
54}
55
56impl PruneSegment {
57    /// Returns an iterator over all variants of [`PruneSegment`].
58    ///
59    /// Excludes deprecated variants that are no longer used, but can still be found in the
60    /// database.
61    pub fn variants() -> impl Iterator<Item = Self> {
62        Self::iter()
63    }
64
65    /// Returns minimum number of blocks to keep in the database for this segment.
66    pub const fn min_blocks(&self) -> u64 {
67        match self {
68            Self::SenderRecovery | Self::TransactionLookup | Self::Receipts | Self::Bodies => 0,
69            Self::ContractLogs | Self::AccountHistory | Self::StorageHistory => {
70                MINIMUM_PRUNING_DISTANCE
71            }
72            #[expect(deprecated)]
73            #[expect(clippy::match_same_arms)]
74            Self::Headers | Self::Transactions | Self::MerkleChangeSets => 0,
75        }
76    }
77
78    /// Returns true if this is [`Self::AccountHistory`].
79    pub const fn is_account_history(&self) -> bool {
80        matches!(self, Self::AccountHistory)
81    }
82
83    /// Returns true if this is [`Self::StorageHistory`].
84    pub const fn is_storage_history(&self) -> bool {
85        matches!(self, Self::StorageHistory)
86    }
87}
88
89/// Prune purpose.
90#[derive(Debug, Clone, Copy)]
91pub enum PrunePurpose {
92    /// Prune data according to user configuration.
93    User,
94    /// Prune data according to highest `static_files` to delete the data from database.
95    StaticFile,
96}
97
98impl PrunePurpose {
99    /// Returns true if the purpose is [`PrunePurpose::User`].
100    pub const fn is_user(self) -> bool {
101        matches!(self, Self::User)
102    }
103
104    /// Returns true if the purpose is [`PrunePurpose::StaticFile`].
105    pub const fn is_static_file(self) -> bool {
106        matches!(self, Self::StaticFile)
107    }
108}
109
110/// `PruneSegment` error type.
111#[derive(Debug, Error, PartialEq, Eq, Clone)]
112pub enum PruneSegmentError {
113    /// Invalid configuration of a prune segment.
114    #[error("the configuration provided for {0} is invalid")]
115    Configuration(PruneSegment),
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_prune_segment_iter_excludes_deprecated() {
124        let segments: Vec<PruneSegment> = PruneSegment::variants().collect();
125
126        // Verify deprecated variants are not included derived iter
127        #[expect(deprecated)]
128        {
129            assert!(!segments.contains(&PruneSegment::Headers));
130            assert!(!segments.contains(&PruneSegment::Transactions));
131            assert!(!segments.contains(&PruneSegment::MerkleChangeSets));
132        }
133    }
134}