Skip to content

feat(snapshots): write Receipt to snapshots during ExecutionStage #6103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 152 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
999a14e
generate snapshots until the tip
joshieDo Nov 15, 2023
34d324d
stats
joshieDo Nov 16, 2023
0a5931a
filter size
joshieDo Nov 16, 2023
c7422ca
dont attempt rename on only stats flag
joshieDo Nov 16, 2023
615e8b4
use default name for generation as well
joshieDo Nov 16, 2023
1119adf
refactor generate snapshots from cli
joshieDo Nov 16, 2023
4a6ae7d
improve stats func
joshieDo Nov 16, 2023
a784733
add more stats
joshieDo Nov 16, 2023
90c5968
add value parser to parallel flag
joshieDo Nov 16, 2023
ab74e35
fmt
joshieDo Nov 16, 2023
b9c51e9
use thread pool instead
joshieDo Nov 17, 2023
94cb5e6
Revert "use thread pool instead"
joshieDo Nov 20, 2023
53189da
optional filters loading
joshieDo Nov 20, 2023
b0d62d5
offsets mmap
joshieDo Nov 24, 2023
f029ccf
add max bytes needed for offsets at beginning of file
joshieDo Nov 24, 2023
a991bc5
small refactor DataReader
joshieDo Nov 24, 2023
92bf0fb
Merge remote-tracking branch 'origin/main' into joshie/gen-snapshots
joshieDo Nov 24, 2023
2c7595c
size returns 0 on unused filters
joshieDo Nov 24, 2023
77e3572
Merge branch 'joshie/gen-snapshots' into joshie/optional-filters
joshieDo Nov 24, 2023
4687864
Merge remote-tracking branch 'origin/main' into joshie/optional-filters
joshieDo Nov 24, 2023
df6d39b
Merge remote-tracking branch 'origin/main' into joshie/optional-filters
joshieDo Nov 27, 2023
96408be
fix docs
joshieDo Nov 27, 2023
b7145dd
remove offsets from NippyJar
joshieDo Dec 3, 2023
b4271e1
add NippyJarWriter
joshieDo Dec 3, 2023
d3a8051
add consistency check
joshieDo Dec 3, 2023
9189c18
fmt
joshieDo Dec 3, 2023
62131f2
clippy
joshieDo Dec 3, 2023
299bfc8
fix some function names
joshieDo Dec 4, 2023
05c5caf
change append_rows docs
joshieDo Dec 4, 2023
d65b1fc
use asref [u8] instead
joshieDo Dec 4, 2023
fc86307
add writer tests with pruning and appending
joshieDo Dec 4, 2023
53afb76
make sure cursor on writer is at the end after truncating
joshieDo Dec 4, 2023
4d86bdb
clippy
joshieDo Dec 4, 2023
42526ea
add some helpers to SnapshotSegment and SegmentHeader
joshieDo Dec 12, 2023
43290a5
add rename and remove to NippyJar
joshieDo Dec 12, 2023
612ee17
added helper enum JarHolder to NippyJarWriter
joshieDo Dec 12, 2023
d86575d
add SnapshotWriter to SnapshotProvider
joshieDo Dec 12, 2023
d155996
add SnapshotProviderRW to providers
joshieDo Dec 12, 2023
56a2a74
write to snapshots on Bodies stage
joshieDo Dec 12, 2023
0dffeb8
feat(snapshots): refactor snapshot data access (#5583)
joshieDo Dec 12, 2023
a026fd4
read configuration from file directly
joshieDo Dec 12, 2023
5e9a3f8
Merge remote-tracking branch 'origin/feat/snapshots' into joshie/writ…
joshieDo Dec 12, 2023
ee87ea2
rename to writer
joshieDo Dec 12, 2023
82714d6
introduce INITIAL_OFFSET_SIZE const
joshieDo Dec 12, 2023
ede4bd5
exit in error if prune request is higher than number of offsets
joshieDo Dec 12, 2023
d827ef5
fmt
joshieDo Dec 12, 2023
0b3c541
handle consistency checks on interrupted pruning
joshieDo Dec 12, 2023
b1bf9ff
error when trying to open a writer with a offset lenght different than 8
joshieDo Dec 13, 2023
60c2852
whitespace
joshieDo Dec 13, 2023
2517658
review fixes
joshieDo Dec 13, 2023
b6e260e
smol fix
joshieDo Dec 13, 2023
b355de0
Merge branch 'joshie/writer-jar' into joshie/tx-snap-sync
joshieDo Dec 13, 2023
f795252
use from_mut for jar writer
joshieDo Dec 14, 2023
abb79c1
clippy
joshieDo Dec 14, 2023
4c9d014
assume there's no static files on stage
joshieDo Dec 15, 2023
457fcfd
refactor: nippy jar writer, offsets (#5760)
shekhirin Dec 15, 2023
31d8ab6
feat: `DatabaseProvider` delegates to `SnapshotProvider` on different…
joshieDo Dec 15, 2023
4c71964
Merge remote-tracking branch 'origin/feat/snapshots' into joshie/writ…
joshieDo Dec 15, 2023
f68f03b
Merge branch 'joshie/writer-jar' into joshie/tx-snap-sync
joshieDo Dec 15, 2023
89bd906
Merge remote-tracking branch 'origin/main' into feat/snapshots
shekhirin Dec 15, 2023
4cf80c7
Merge remote-tracking branch 'origin/main' into feat/snapshots
shekhirin Dec 15, 2023
16db801
query receipts segment in receipts_by_tx_range
shekhirin Dec 15, 2023
69d8691
Merge remote-tracking branch 'origin/feat/snapshots' into joshie/writ…
joshieDo Dec 15, 2023
eccd512
Merge branch 'joshie/writer-jar' into joshie/tx-snap-sync
joshieDo Dec 15, 2023
54831d8
Update crates/storage/nippy-jar/src/writer.rs
joshieDo Dec 15, 2023
54b4877
Update crates/storage/nippy-jar/src/writer.rs
joshieDo Dec 15, 2023
4ecfcf2
use sync_all
joshieDo Dec 15, 2023
aad40d4
add doc about self heal on jar writer
joshieDo Dec 15, 2023
144c28b
Merge branch 'joshie/writer-jar' into joshie/tx-snap-sync
joshieDo Dec 15, 2023
6a33e75
commit snapshotter at the end of execution
joshieDo Dec 15, 2023
ae79086
checks before append/unwind static
joshieDo Dec 18, 2023
30a35c2
feat: refactor indexing inside `SnapshotProvider` (#5780)
joshieDo Dec 18, 2023
d458a51
Merge remote-tracking branch 'origin/feat/snapshots' into joshie/writ…
joshieDo Dec 18, 2023
0d3dc0a
Merge branch 'joshie/writer-jar' into joshie/tx-snap-sync
joshieDo Dec 18, 2023
5e720d1
add missing stage error
joshieDo Dec 18, 2023
365468d
fix rename
joshieDo Dec 18, 2023
8732595
Merge remote-tracking branch 'origin/main' into joshie/tx-snap-sync
shekhirin Dec 18, 2023
436e606
chore(nippy-jar): clippy (#5818)
shekhirin Dec 20, 2023
c58d6a5
feat(storage, snapshot): append receipt (#5817)
shekhirin Dec 26, 2023
5be02b8
feat: remove `tx_range` from filename (#5823)
joshieDo Jan 2, 2024
8f80230
unwind when missing snapshot data
joshieDo Jan 10, 2024
b475eae
no dangling snapshot data without conf
joshieDo Jan 10, 2024
579da38
handle empty blocks
joshieDo Jan 10, 2024
c9c8a9f
SnapshotProviderRW::open uses start of the fixed range instead
joshieDo Jan 10, 2024
882bd98
remove debug_assert
joshieDo Jan 10, 2024
79a789f
Merge remote-tracking branch 'origin/main' into joshie/tx-snap-sync
joshieDo Jan 10, 2024
a89fdde
revert test change
joshieDo Jan 10, 2024
a32a017
minor changes
joshieDo Jan 10, 2024
ffdc327
fix clippy
joshieDo Jan 11, 2024
81635e3
fix test_snap with new changes
joshieDo Jan 11, 2024
de73878
provider map keys come from the fixed range instead
joshieDo Jan 11, 2024
63c3b15
add sanity consistency checks on appending
joshieDo Jan 11, 2024
50e4073
clippy
joshieDo Jan 11, 2024
df3e020
make sure prepare_jar uses fixed block range for filename
joshieDo Jan 11, 2024
d72035d
commit on truncate
joshieDo Jan 15, 2024
d9d41cb
add more docs and CowJar
joshieDo Jan 15, 2024
20039a3
adds some notes about commit on methods that use truncate
joshieDo Jan 15, 2024
3d0a14f
add a test set_block_range
joshieDo Jan 15, 2024
aa269f2
invalidate cached static file on writer commit
joshieDo Jan 15, 2024
3a183cf
refactor update_index
joshieDo Jan 15, 2024
9d62f7d
query TransactionBlock for next tx num
shekhirin Jan 15, 2024
464632a
Merge branch 'feat/static-files' into joshie/tx-snap-sync
joshieDo Jan 16, 2024
cc02564
fix cargo docs
joshieDo Jan 16, 2024
5e5c6cf
fix bug on unwind to 0
joshieDo Jan 17, 2024
22a4042
append receipts to static files
joshieDo Jan 17, 2024
04e2831
spread SnapshotProviderRWRefMut
joshieDo Jan 17, 2024
26b18d8
return empty if jar with 0 rows is queried
joshieDo Jan 17, 2024
cad373c
use unadjusted prune mode instead
joshieDo Jan 17, 2024
4470e69
if tx range is None on receipts/txes, clear from tx index
joshieDo Jan 17, 2024
ce9f75b
make sure next_tx_num is 1 on insert_block
joshieDo Jan 17, 2024
8d6d17d
use both db and snapshots on sanity_execute_unwind test
joshieDo Jan 17, 2024
fbc5027
use both db and snapshots on sanity_execution_of_block test
joshieDo Jan 17, 2024
312f683
fix get_take_block_transaction_range_recover_senders with tx_num star…
joshieDo Jan 17, 2024
13e4b66
fix insert_block_with_prune_modes with tx_num starting at 1
joshieDo Jan 17, 2024
cc75fb6
create_test_provider_factory is created with a snapshot directory and…
joshieDo Jan 17, 2024
15156df
make sure ef-tests creates the snapshotprovider on its factory
joshieDo Jan 17, 2024
8a21242
fix tx_num to start at 0 not 1
joshieDo Jan 17, 2024
4d4815b
Merge branch 'joshie/tx-snap-sync' into joshie/receipts-snap-sync
joshieDo Jan 17, 2024
c4162a7
tx_num starts at 0 not 1
joshieDo Jan 17, 2024
17862c7
fmt
joshieDo Jan 17, 2024
7ab3287
Update crates/interfaces/src/provider.rs
joshieDo Jan 17, 2024
61e9f22
Update crates/storage/provider/src/providers/snapshot/manager.rs
joshieDo Jan 17, 2024
8dcd208
Update crates/stages/src/error.rs
joshieDo Jan 17, 2024
4cf39f2
Update crates/primitives/src/snapshot/segment.rs
joshieDo Jan 17, 2024
c416918
Update crates/stages/src/error.rs
joshieDo Jan 17, 2024
a5552ff
Update crates/stages/src/error.rs
joshieDo Jan 17, 2024
1517133
find_fixed_range no longer takes an interval arg
joshieDo Jan 17, 2024
c6daaee
add segment to StageError::MissingSnapshotData
joshieDo Jan 17, 2024
f09aeae
use reth_primitives::fs::create_dir_all instead
joshieDo Jan 17, 2024
586287c
make snapshot_provider private on DbProvider
joshieDo Jan 17, 2024
fcf79ab
fix parse_filename doc
joshieDo Jan 17, 2024
68c77dd
replace OsString with str
joshieDo Jan 17, 2024
d55c9f7
add more docs on update_index
joshieDo Jan 17, 2024
0bc9b91
Update crates/primitives/src/snapshot/segment.rs
joshieDo Jan 17, 2024
dd749fc
unify block_range and tx_range api on segment header
joshieDo Jan 17, 2024
40b5ee7
Merge branch 'joshie/tx-snap-sync' into joshie/receipts-snap-sync
joshieDo Jan 17, 2024
2a5fc4f
doc prune_transactions
joshieDo Jan 23, 2024
782f7e3
add some more docs wrt snapshot tx num != db tx num
joshieDo Jan 23, 2024
b21950b
entry API on get_writer
joshieDo Jan 23, 2024
957a6e1
add more doc on update_index
joshieDo Jan 23, 2024
f78a00d
Merge branch 'joshie/tx-snap-sync' into joshie/receipts-snap-sync
joshieDo Jan 24, 2024
153a36d
add more docs and changes name to try_prepare_snapshotter
joshieDo Jan 24, 2024
f340fde
more docs
joshieDo Jan 24, 2024
f94bdbc
use get_writer
joshieDo Jan 26, 2024
8bb80fc
Merge remote-tracking branch 'origin/feat/static-files' into joshie/r…
joshieDo Jan 26, 2024
5cc4cf4
Update crates/storage/provider/src/providers/snapshot/manager.rs
joshieDo Jan 26, 2024
3e643fe
Merge remote-tracking branch 'origin/feat/static-files' into joshie/r…
joshieDo Jan 26, 2024
fd86e88
Merge branch 'joshie/receipts-snap-sync' of github.com:paradigmxyz/re…
joshieDo Jan 26, 2024
815f100
clean up write_to_storage
joshieDo Jan 26, 2024
86e6760
split prepare_snapshotter and more docs
joshieDo Jan 26, 2024
1109058
Merge remote-tracking branch 'origin/feat/static-files' into joshie/r…
joshieDo Jan 29, 2024
e57e820
Update crates/stages/src/stages/execution.rs
joshieDo Jan 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/reth/src/commands/debug_cmd/in_memory_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl Command {
.map_err(|_| BlockValidationError::SenderRecoveryError)?,
None,
)?;
block_state.write_to_db(provider_rw.tx_ref(), OriginalValuesKnown::No)?;
block_state.write_to_storage(provider_rw.tx_ref(), None, OriginalValuesKnown::No)?;
let storage_lists = provider_rw.changed_storages_with_range(block.number..=block.number)?;
let storages = provider_rw.plain_state_storages(storage_lists)?;
provider_rw.insert_storage_for_hashing(storages)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/node-core/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ pub fn insert_genesis_state<DB: Database>(
0,
);

bundle.write_to_db(tx, OriginalValuesKnown::Yes)?;
bundle.write_to_storage(tx, None, OriginalValuesKnown::Yes)?;

Ok(())
}
Expand Down
381 changes: 269 additions & 112 deletions crates/stages/src/stages/execution.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions crates/storage/db/src/snapshot/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ impl<'a> SnapshotCursor<'a> {
key_or_num: KeyOrNumber<'_>,
mask: usize,
) -> ProviderResult<Option<Vec<&'_ [u8]>>> {
if self.jar().rows() == 0 {
return Ok(None)
}

let row = match key_or_num {
KeyOrNumber::Key(k) => self.row_by_key_with_cols(k, mask),
KeyOrNumber::Number(n) => {
Expand Down
5 changes: 5 additions & 0 deletions crates/storage/nippy-jar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ impl<H: NippyJarHeader> NippyJar<H> {
&self.user_header
}

/// Gets total rows in jar.
pub fn rows(&self) -> usize {
self.rows
}

/// Returns the size of inclusion filter
pub fn filter_size(&self) -> usize {
self.size()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use crate::{StateChanges, StateReverts};
use crate::{providers::SnapshotProviderRWRefMut, StateChanges, StateReverts};
use reth_db::{
cursor::{DbCursorRO, DbCursorRW},
tables,
transaction::{DbTx, DbTxMut},
};
use reth_interfaces::db::DatabaseError;
use reth_interfaces::provider::{ProviderError, ProviderResult};
use reth_primitives::{
logs_bloom,
revm::compat::{into_reth_acc, into_revm_acc},
Account, Address, BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts, StorageEntry, B256,
U256,
Account, Address, BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts, SnapshotSegment,
StorageEntry, B256, U256,
};
use reth_trie::HashedPostState;
use revm::{
Expand Down Expand Up @@ -285,15 +285,21 @@ impl BundleStateWithReceipts {
std::mem::swap(&mut self.bundle, &mut other)
}

/// Write bundle state to database.
/// Write bundle state to database and receipts to either database or static files if
/// `snapshotter` is `Some`. It should be none if there is any kind of pruning/filtering over
/// the receipts.
///
/// `omit_changed_check` should be set to true of bundle has some of it data
/// detached, This would make some original values not known.
pub fn write_to_db<TX: DbTxMut + DbTx>(
pub fn write_to_storage<TX>(
self,
tx: &TX,
mut snapshotter: Option<SnapshotProviderRWRefMut<'_>>,
is_value_known: OriginalValuesKnown,
) -> Result<(), DatabaseError> {
) -> ProviderResult<()>
where
TX: DbTxMut + DbTx,
{
let (plain_state, reverts) = self.bundle.into_plain_state_and_reverts(is_value_known);

StateReverts(reverts).write_to_db(tx, self.first_block)?;
Expand All @@ -303,15 +309,22 @@ impl BundleStateWithReceipts {
let mut receipts_cursor = tx.cursor_write::<tables::Receipts>()?;

for (idx, receipts) in self.receipts.into_iter().enumerate() {
if !receipts.is_empty() {
let block_number = self.first_block + idx as u64;
let (_, body_indices) =
bodies_cursor.seek_exact(block_number)?.unwrap_or_else(|| {
let last_available = bodies_cursor.last().ok().flatten().map(|(number, _)| number);
panic!("body indices for block {block_number} must exist. last available block number: {last_available:?}");
});

let first_tx_index = body_indices.first_tx_num();
let block_number = self.first_block + idx as u64;
let first_tx_index = bodies_cursor
.seek_exact(block_number)?
.map(|(_, indices)| indices.first_tx_num())
.ok_or_else(|| ProviderError::BlockBodyIndicesNotFound(block_number))?;

if let Some(snapshotter) = &mut snapshotter {
// Increment block on static file header.
snapshotter.increment_block(SnapshotSegment::Receipts)?;

for (tx_idx, receipt) in receipts.into_iter().enumerate() {
let receipt = receipt
.expect("receipt should not be filtered when saving to static files.");
snapshotter.append_receipt(first_tx_index + tx_idx as u64, receipt)?;
}
} else if !receipts.is_empty() {
for (tx_idx, receipt) in receipts.into_iter().enumerate() {
if let Some(receipt) = receipt {
receipts_cursor.append(first_tx_index + tx_idx as u64, receipt)?;
Expand Down Expand Up @@ -556,7 +569,7 @@ mod tests {
state.merge_transitions(BundleRetention::Reverts);

BundleStateWithReceipts::new(state.take_bundle(), Receipts::new(), 1)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.write_to_storage(provider.tx_ref(), None, OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

// Check plain storage state
Expand Down Expand Up @@ -654,7 +667,7 @@ mod tests {

state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(state.take_bundle(), Receipts::new(), 2)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.write_to_storage(provider.tx_ref(), None, OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

assert_eq!(
Expand Down Expand Up @@ -718,7 +731,7 @@ mod tests {
)]));
init_state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(init_state.take_bundle(), Receipts::new(), 0)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.write_to_storage(provider.tx_ref(), None, OriginalValuesKnown::Yes)
.expect("Could not write init bundle state to DB");

let mut state = State::builder().with_bundle_update().build();
Expand Down Expand Up @@ -863,7 +876,7 @@ mod tests {
let bundle = state.take_bundle();

BundleStateWithReceipts::new(bundle, Receipts::new(), 1)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.write_to_storage(provider.tx_ref(), None, OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

let mut storage_changeset_cursor = provider
Expand Down Expand Up @@ -1026,7 +1039,7 @@ mod tests {
)]));
init_state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(init_state.take_bundle(), Receipts::new(), 0)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.write_to_storage(provider.tx_ref(), None, OriginalValuesKnown::Yes)
.expect("Could not write init bundle state to DB");

let mut state = State::builder().with_bundle_update().build();
Expand Down Expand Up @@ -1071,7 +1084,7 @@ mod tests {
// Commit block #1 changes to the database.
state.merge_transitions(BundleRetention::Reverts);
BundleStateWithReceipts::new(state.take_bundle(), Receipts::new(), 1)
.write_to_db(provider.tx_ref(), OriginalValuesKnown::Yes)
.write_to_storage(provider.tx_ref(), None, OriginalValuesKnown::Yes)
.expect("Could not write bundle state to DB");

let mut storage_changeset_cursor = provider
Expand Down
8 changes: 4 additions & 4 deletions crates/storage/provider/src/providers/database/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ pub struct DatabaseProvider<TX> {
}

impl<TX> DatabaseProvider<TX> {
/// Returns snapshot provider
pub fn snapshot_provider(&self) -> Option<Arc<SnapshotProvider>> {
self.snapshot_provider.clone()
/// Returns a snapshot provider reference
pub fn snapshot_provider(&self) -> Option<&Arc<SnapshotProvider>> {
self.snapshot_provider.as_ref()
}
}

Expand Down Expand Up @@ -2499,7 +2499,7 @@ impl<TX: DbTxMut + DbTx> BlockWriter for DatabaseProvider<TX> {

// Write state and changesets to the database.
// Must be written after blocks because of the receipt lookup.
state.write_to_db(self.tx_ref(), OriginalValuesKnown::No)?;
state.write_to_storage(self.tx_ref(), None, OriginalValuesKnown::No)?;
durations_recorder.record_relative(metrics::Action::InsertState);

// insert hashes and intermediate merkle nodes
Expand Down
5 changes: 4 additions & 1 deletion crates/storage/provider/src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ mod bundle_state_provider;
mod chain_info;
mod database;
mod snapshot;
pub use snapshot::{SnapshotJarProvider, SnapshotProvider, SnapshotProviderRW, SnapshotWriter};
pub use snapshot::{
SnapshotJarProvider, SnapshotProvider, SnapshotProviderRW, SnapshotProviderRWRefMut,
SnapshotWriter,
};
mod state;
use crate::{providers::chain_info::ChainInfoTracker, traits::BlockSource};
pub use bundle_state_provider::BundleStateProvider;
Expand Down
25 changes: 16 additions & 9 deletions crates/storage/provider/src/providers/snapshot/manager.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use super::{LoadedJar, SnapshotJarProvider, SnapshotProviderRW, BLOCKS_PER_SNAPSHOT};
use super::{
LoadedJar, SnapshotJarProvider, SnapshotProviderRW, SnapshotProviderRWRefMut,
BLOCKS_PER_SNAPSHOT,
};
use crate::{
to_range, BlockHashReader, BlockNumReader, BlockReader, BlockSource, HeaderProvider,
ReceiptProvider, TransactionVariant, TransactionsProvider, TransactionsProviderExt,
WithdrawalsProvider,
};
use dashmap::{
mapref::{entry::Entry as DashMapEntry, one::RefMut},
DashMap,
};
use dashmap::{mapref::entry::Entry as DashMapEntry, DashMap};
use parking_lot::RwLock;
use reth_db::{
codecs::CompactU256,
Expand Down Expand Up @@ -264,6 +264,13 @@ impl SnapshotProvider {
index.insert(tx_end, current_block_range.clone());
})
.or_insert_with(|| BTreeMap::from([(tx_end, current_block_range)]));
} else if let Some(1) = tx_index.get(&segment).map(|index| index.len()) {
// Only happens if we unwind all the txs/receipts from the first static file.
// Should only happen in test scenarios.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, isn't it possible that we have index of length one during the normal node operation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i may be missing something, but i think highly unlikely...

if matches!(segment, SnapshotSegment::Receipts | SnapshotSegment::Transactions)
{
tx_index.remove(&segment);
}
}

// Update the cached provider.
Expand Down Expand Up @@ -420,13 +427,13 @@ pub trait SnapshotWriter {
&self,
block: BlockNumber,
segment: SnapshotSegment,
) -> ProviderResult<RefMut<'_, SnapshotSegment, SnapshotProviderRW<'static>>>;
) -> ProviderResult<SnapshotProviderRWRefMut<'_>>;

/// Returns a mutable reference to a [`SnapshotProviderRW`] of the latest [`SnapshotSegment`].
fn latest_writer(
&self,
segment: SnapshotSegment,
) -> ProviderResult<RefMut<'_, SnapshotSegment, SnapshotProviderRW<'static>>>;
) -> ProviderResult<SnapshotProviderRWRefMut<'_>>;

/// Commits all changes of all [`SnapshotProviderRW`] of all [`SnapshotSegment`].
fn commit(&self) -> ProviderResult<()>;
Expand All @@ -437,7 +444,7 @@ impl SnapshotWriter for Arc<SnapshotProvider> {
&self,
block: BlockNumber,
segment: SnapshotSegment,
) -> ProviderResult<RefMut<'_, SnapshotSegment, SnapshotProviderRW<'static>>> {
) -> ProviderResult<SnapshotProviderRWRefMut<'_>> {
Ok(match self.writers.entry(segment) {
DashMapEntry::Occupied(entry) => entry.into_ref(),
DashMapEntry::Vacant(entry) => {
Expand All @@ -449,7 +456,7 @@ impl SnapshotWriter for Arc<SnapshotProvider> {
fn latest_writer(
&self,
segment: SnapshotSegment,
) -> ProviderResult<RefMut<'_, SnapshotSegment, SnapshotProviderRW<'static>>> {
) -> ProviderResult<SnapshotProviderRWRefMut<'_>> {
self.get_writer(self.get_highest_snapshot_block(segment).unwrap_or_default(), segment)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/storage/provider/src/providers/snapshot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod jar;
pub use jar::SnapshotJarProvider;

mod writer;
pub use writer::SnapshotProviderRW;
pub use writer::{SnapshotProviderRW, SnapshotProviderRWRefMut};

use reth_interfaces::provider::ProviderResult;
use reth_nippy_jar::NippyJar;
Expand Down
19 changes: 19 additions & 0 deletions crates/storage/provider/src/providers/snapshot/writer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::SnapshotProvider;
use dashmap::mapref::one::RefMut;
use reth_codecs::Compact;
use reth_interfaces::provider::{ProviderError, ProviderResult};
use reth_nippy_jar::{NippyJar, NippyJarError, NippyJarWriter};
Expand All @@ -9,6 +10,9 @@ use reth_primitives::{
};
use std::{ops::Deref, path::PathBuf, sync::Arc};

/// Mutable reference to a dashmap element of [`SnapshotProviderRW`].
pub type SnapshotProviderRWRefMut<'a> = RefMut<'a, SnapshotSegment, SnapshotProviderRW<'static>>;

#[derive(Debug)]
/// Extends `SnapshotProvider` with writing capabilities
pub struct SnapshotProviderRW<'a> {
Expand Down Expand Up @@ -274,6 +278,21 @@ impl<'a> SnapshotProviderRW<'a> {
self.truncate(segment, number, Some(last_block))
}

/// Prunes `to_delete` number of receipts from snapshots.
///
/// # Note
/// Commits to the configuration file at the end.
pub fn prune_receipts(
&mut self,
to_delete: u64,
last_block: BlockNumber,
) -> ProviderResult<()> {
let segment = SnapshotSegment::Receipts;
debug_assert!(self.writer.user_header().segment() == segment);

self.truncate(segment, to_delete, Some(last_block))
}

#[cfg(any(test, feature = "test-utils"))]
/// Helper function to override block range for testing.
pub fn set_block_range(&mut self, block_range: std::ops::RangeInclusive<BlockNumber>) {
Expand Down
4 changes: 2 additions & 2 deletions crates/storage/provider/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::ProviderFactory;
use reth_db::{
test_utils::{create_test_rw_db, TempDatabase},
test_utils::{create_test_rw_db, create_test_snapshots_dir, TempDatabase},
DatabaseEnv,
};
use reth_primitives::{ChainSpec, MAINNET};
Expand All @@ -27,5 +27,5 @@ pub fn create_test_provider_factory_with_chain_spec(
chain_spec: Arc<ChainSpec>,
) -> ProviderFactory<Arc<TempDatabase<DatabaseEnv>>> {
let db = create_test_rw_db();
ProviderFactory::new(db, chain_spec)
ProviderFactory::new(db, chain_spec).with_snapshots(create_test_snapshots_dir()).unwrap()
}
4 changes: 3 additions & 1 deletion testing/ef-tests/src/cases/blockchain_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
Case, Error, Suite,
};
use alloy_rlp::Decodable;
use reth_db::test_utils::create_test_rw_db;
use reth_db::test_utils::{create_test_rw_db, create_test_snapshots_dir};
use reth_primitives::{BlockBody, SealedBlock};
use reth_provider::{BlockWriter, HashingWriter, ProviderFactory};
use reth_stages::{stages::ExecutionStage, ExecInput, Stage};
Expand Down Expand Up @@ -78,6 +78,8 @@ impl Case for BlockchainTestCase {
// Create a new test database and initialize a provider for the test case.
let db = create_test_rw_db();
let provider = ProviderFactory::new(db.as_ref(), Arc::new(case.network.clone().into()))
.with_snapshots(create_test_snapshots_dir())
.map_err(|err| Error::RethError(err.into()))?
.provider_rw()
.unwrap();

Expand Down