chore: move receipts pruning to provider (#13886)

This commit is contained in:
Arsenii Kulikov
2025-01-22 17:41:13 +04:00
committed by GitHub
parent cd44fc3d09
commit 23ebf96188
8 changed files with 75 additions and 250 deletions

View File

@ -19,7 +19,7 @@ use crate::{
StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider,
TransactionsProviderExt, TrieWriter, WithdrawalsProvider,
};
use alloy_consensus::{transaction::TransactionMeta, BlockHeader, Header};
use alloy_consensus::{transaction::TransactionMeta, BlockHeader, Header, TxReceipt};
use alloy_eips::{eip2718::Encodable2718, eip4895::Withdrawals, BlockHashOrNumber};
use alloy_primitives::{
keccak256,
@ -51,7 +51,9 @@ use reth_primitives::{
StaticFileSegment, StorageEntry,
};
use reth_primitives_traits::{Block as _, BlockBody as _, SignedTransaction};
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
use reth_prune_types::{
PruneCheckpoint, PruneMode, PruneModes, PruneSegment, MINIMUM_PRUNING_DISTANCE,
};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{
BlockBodyIndicesProvider, BlockBodyReader, NodePrimitivesProvider, OmmersProvider,
@ -1783,9 +1785,11 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateWriter
write_receipts_to: StorageLocation,
) -> ProviderResult<()> {
let first_block = execution_outcome.first_block();
let block_count = execution_outcome.receipts.len() as u64;
let block_range = first_block..=first_block.saturating_add(block_count).saturating_sub(1);
let last_block = *block_range.end();
let block_count = execution_outcome.len() as u64;
let last_block = execution_outcome.last_block();
let block_range = first_block..=last_block;
let tip = self.last_block_number()?.max(last_block);
let (plain_state, reverts) =
execution_outcome.bundle.to_plain_state_and_reverts(is_value_known);
@ -1827,6 +1831,20 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateWriter
.then(|| self.static_file_provider.get_writer(first_block, StaticFileSegment::Receipts))
.transpose()?;
let has_contract_log_filter = !self.prune_modes.receipts_log_filter.is_empty();
let contract_log_pruner = self.prune_modes.receipts_log_filter.group_by_block(tip, None)?;
// All receipts from the last 128 blocks are required for blockchain tree, even with
// [`PruneSegment::ContractLogs`].
let prunable_receipts =
PruneMode::Distance(MINIMUM_PRUNING_DISTANCE).should_prune(first_block, tip);
// Prepare set of addresses which logs should not be pruned.
let mut allowed_addresses: HashSet<Address, _> = HashSet::new();
for (_, addresses) in contract_log_pruner.range(..first_block) {
allowed_addresses.extend(addresses.iter().copied());
}
for (idx, (receipts, first_tx_index)) in
execution_outcome.receipts.iter().zip(block_indices).enumerate()
{
@ -1837,9 +1855,35 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider> StateWriter
writer.increment_block(block_number)?;
}
// Skip writing receipts if pruning configuration requires us to.
if prunable_receipts &&
self.prune_modes
.receipts
.is_some_and(|mode| mode.should_prune(block_number, tip))
{
continue
}
// If there are new addresses to retain after this block number, track them
if let Some(new_addresses) = contract_log_pruner.get(&block_number) {
allowed_addresses.extend(new_addresses.iter().copied());
}
for (idx, receipt) in receipts.iter().enumerate() {
let receipt_idx = first_tx_index + idx as u64;
if let Some(receipt) = receipt {
// Skip writing receipt if log filter is active and it does not have any logs to
// retain
if prunable_receipts &&
has_contract_log_filter &&
!receipt
.logs()
.iter()
.any(|log| allowed_addresses.contains(&log.address))
{
continue
}
if let Some(writer) = &mut receipts_static_writer {
writer.append_receipt(receipt_idx, receipt)?;
}