Skip to content

Commit 34e2b9f

Browse files
committed
feat(prune): Add MerkleChangeSets segment
1 parent 7381462 commit 34e2b9f

File tree

5 files changed

+114
-7
lines changed

5 files changed

+114
-7
lines changed

crates/prune/prune/src/segments/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ pub use static_file::{
1515
use std::{fmt::Debug, ops::RangeInclusive};
1616
use tracing::error;
1717
pub use user::{
18-
AccountHistory, Receipts as UserReceipts, ReceiptsByLogs, SenderRecovery, StorageHistory,
19-
TransactionLookup,
18+
AccountHistory, MerkleChangeSets, Receipts as UserReceipts, ReceiptsByLogs, SenderRecovery,
19+
StorageHistory, TransactionLookup,
2020
};
2121

2222
/// A segment represents a pruning of some portion of the data.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use crate::{
2+
db_ext::DbTxPruneExt,
3+
segments::{PruneInput, Segment},
4+
PrunerError,
5+
};
6+
use alloy_primitives::B256;
7+
use reth_db_api::{models::BlockNumberHashedAddress, table::Value, tables, transaction::DbTxMut};
8+
use reth_primitives_traits::NodePrimitives;
9+
use reth_provider::{
10+
errors::provider::ProviderResult, BlockReader, DBProvider, NodePrimitivesProvider,
11+
PruneCheckpointWriter, TransactionsProvider,
12+
};
13+
use reth_prune_types::{
14+
PruneCheckpoint, PruneMode, PrunePurpose, PruneSegment, SegmentOutput, SegmentOutputCheckpoint,
15+
};
16+
use tracing::{instrument, trace};
17+
18+
#[derive(Debug)]
19+
pub struct MerkleChangeSets {
20+
mode: PruneMode,
21+
}
22+
23+
impl MerkleChangeSets {
24+
pub const fn new(mode: PruneMode) -> Self {
25+
Self { mode }
26+
}
27+
}
28+
29+
impl<Provider> Segment<Provider> for MerkleChangeSets
30+
where
31+
Provider: DBProvider<Tx: DbTxMut>
32+
+ PruneCheckpointWriter
33+
+ TransactionsProvider
34+
+ BlockReader
35+
+ NodePrimitivesProvider<Primitives: NodePrimitives<Receipt: Value>>,
36+
{
37+
fn segment(&self) -> PruneSegment {
38+
PruneSegment::MerkleChangeSets
39+
}
40+
41+
fn mode(&self) -> Option<PruneMode> {
42+
Some(self.mode)
43+
}
44+
45+
fn purpose(&self) -> PrunePurpose {
46+
PrunePurpose::User
47+
}
48+
49+
#[instrument(level = "trace", target = "pruner", skip(self, provider), ret)]
50+
fn prune(&self, provider: &Provider, input: PruneInput) -> Result<SegmentOutput, PrunerError> {
51+
let Some(block_range) = input.get_next_block_range() else {
52+
trace!(target: "pruner", "No change sets to prune");
53+
return Ok(SegmentOutput::done())
54+
};
55+
56+
let block_range_end = *block_range.end();
57+
let mut limiter = input.limiter;
58+
let mut last_pruned_block = block_range_end;
59+
60+
for block in block_range {
61+
let (pruned, done) =
62+
provider.tx_ref().prune_table_with_range::<tables::StoragesTrieChangeSets>(
63+
BlockNumberHashedAddress::from((block, B256::ZERO))..,
64+
&mut limiter,
65+
|_| false,
66+
|row| last_pruned_block = row.0 .0 .0,
67+
)?;
68+
69+
trace!(target: "pruner", %pruned, %done, "Pruned storages change sets");
70+
}
71+
72+
let (pruned, done) =
73+
provider.tx_ref().prune_table_with_range::<tables::AccountsTrieChangeSets>(
74+
block_range.clone(),
75+
&mut limiter,
76+
|_| false,
77+
|row| last_pruned_block = row.0,
78+
)?;
79+
80+
trace!(target: "pruner", %pruned, %done, "Pruned accounts change sets");
81+
82+
let progress = limiter.progress(done);
83+
84+
Ok(SegmentOutput {
85+
progress,
86+
pruned,
87+
checkpoint: Some(SegmentOutputCheckpoint {
88+
block_number: Some(last_pruned_block),
89+
tx_number: None,
90+
}),
91+
})
92+
}
93+
94+
fn save_checkpoint(
95+
&self,
96+
provider: &Provider,
97+
checkpoint: PruneCheckpoint,
98+
) -> ProviderResult<()> {
99+
provider.save_prune_checkpoint(PruneSegment::MerkleChangeSets, checkpoint)
100+
}
101+
}

crates/prune/prune/src/segments/user/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
mod account_history;
22
mod history;
3+
mod merkle_change_sets;
34
mod receipts;
45
mod receipts_by_logs;
56
mod sender_recovery;
67
mod storage_history;
78
mod transaction_lookup;
89

910
pub use account_history::AccountHistory;
11+
pub use merkle_change_sets::MerkleChangeSets;
1012
pub use receipts::Receipts;
1113
pub use receipts_by_logs::ReceiptsByLogs;
1214
pub use sender_recovery::SenderRecovery;

crates/prune/types/src/segment.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub enum PruneSegment {
1515
TransactionLookup,
1616
/// Prune segment responsible for all rows in `Receipts` table.
1717
Receipts,
18+
/// Prune segment responsible for all rows in `AccountsTrieChangeSets` and
19+
/// `StoragesTrieChangeSets` table.
20+
MerkleChangeSets,
1821
/// Prune segment responsible for some rows in `Receipts` table filtered by logs.
1922
ContractLogs,
2023
/// Prune segment responsible for the `AccountChangeSets` and `AccountsHistory` tables.
@@ -44,9 +47,10 @@ impl PruneSegment {
4447
0
4548
}
4649
Self::Receipts if purpose.is_static_file() => 0,
47-
Self::ContractLogs | Self::AccountHistory | Self::StorageHistory => {
48-
MINIMUM_PRUNING_DISTANCE
49-
}
50+
Self::ContractLogs |
51+
Self::AccountHistory |
52+
Self::StorageHistory |
53+
Self::MerkleChangeSets |
5054
Self::Receipts => MINIMUM_PRUNING_DISTANCE,
5155
}
5256
}

crates/storage/provider/src/providers/blockchain_provider.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,7 +2272,7 @@ mod tests {
22722272

22732273
// Invalid/Non-existent argument should return `None`
22742274
{
2275-
call_method!($arg_count, provider, $method, |_,_,_,_| ( ($invalid_args, None)), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
2275+
call_method!($arg_count, provider, $method, |_,_,_,_| ($invalid_args, None), tx_num, tx_hash, &in_memory_blocks[0], &receipts);
22762276
}
22772277

22782278
// Check that the item is only in memory and not in database
@@ -2283,7 +2283,7 @@ mod tests {
22832283
call_method!($arg_count, provider, $method, |_,_,_,_| (args.clone(), expected_item), tx_num, tx_hash, last_mem_block, &receipts);
22842284

22852285
// Ensure the item is not in storage
2286-
call_method!($arg_count, provider.database, $method, |_,_,_,_| ( (args, None)), tx_num, tx_hash, last_mem_block, &receipts);
2286+
call_method!($arg_count, provider.database, $method, |_,_,_,_| (args, None), tx_num, tx_hash, last_mem_block, &receipts);
22872287
}
22882288
)*
22892289
}};

0 commit comments

Comments
 (0)