Skip to main content

reth_prune_types/
segment.rs

1#![allow(deprecated)] // necessary to all defining deprecated `PruneSegment` variants
2
3use crate::{MINIMUM_DISTANCE, MINIMUM_UNWIND_SAFE_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    /// Prunes account changesets (static files/MDBX) and `AccountsHistory`.
28    AccountHistory,
29    /// Prunes storage changesets (static files/MDBX) and `StoragesHistory`.
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 => 0,
69            Self::Receipts | Self::Bodies => MINIMUM_DISTANCE,
70            Self::ContractLogs | Self::AccountHistory | Self::StorageHistory => {
71                MINIMUM_UNWIND_SAFE_DISTANCE
72            }
73            #[expect(deprecated)]
74            #[expect(clippy::match_same_arms)]
75            Self::Headers | Self::Transactions | Self::MerkleChangeSets => 0,
76        }
77    }
78
79    /// Returns true if this is [`Self::AccountHistory`].
80    pub const fn is_account_history(&self) -> bool {
81        matches!(self, Self::AccountHistory)
82    }
83
84    /// Returns true if this is [`Self::StorageHistory`].
85    pub const fn is_storage_history(&self) -> bool {
86        matches!(self, Self::StorageHistory)
87    }
88}
89
90/// Prune purpose.
91#[derive(Debug, Clone, Copy)]
92pub enum PrunePurpose {
93    /// Prune data according to user configuration.
94    User,
95    /// Prune data according to highest `static_files` to delete the data from database.
96    StaticFile,
97}
98
99impl PrunePurpose {
100    /// Returns true if the purpose is [`PrunePurpose::User`].
101    pub const fn is_user(self) -> bool {
102        matches!(self, Self::User)
103    }
104
105    /// Returns true if the purpose is [`PrunePurpose::StaticFile`].
106    pub const fn is_static_file(self) -> bool {
107        matches!(self, Self::StaticFile)
108    }
109}
110
111/// `PruneSegment` error type.
112#[derive(Debug, Error, PartialEq, Eq, Clone)]
113pub enum PruneSegmentError {
114    /// Invalid configuration of a prune segment.
115    #[error("the configuration provided for {0} is invalid")]
116    Configuration(PruneSegment),
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_prune_segment_iter_excludes_deprecated() {
125        let segments: Vec<PruneSegment> = PruneSegment::variants().collect();
126
127        // Verify deprecated variants are not included derived iter
128        #[expect(deprecated)]
129        {
130            assert!(!segments.contains(&PruneSegment::Headers));
131            assert!(!segments.contains(&PruneSegment::Transactions));
132            assert!(!segments.contains(&PruneSegment::MerkleChangeSets));
133        }
134    }
135}