reth_static_file/segments/
transactions.rs

1use crate::segments::Segment;
2use alloy_primitives::BlockNumber;
3use reth_codecs::Compact;
4use reth_db::{table::Value, tables};
5use reth_db_api::{cursor::DbCursorRO, transaction::DbTx};
6use reth_primitives_traits::NodePrimitives;
7use reth_provider::{
8    providers::StaticFileWriter, BlockReader, DBProvider, StaticFileProviderFactory,
9};
10use reth_static_file_types::StaticFileSegment;
11use reth_storage_errors::provider::{ProviderError, ProviderResult};
12use std::ops::RangeInclusive;
13
14/// Static File segment responsible for [`StaticFileSegment::Transactions`] part of data.
15#[derive(Debug, Default)]
16pub struct Transactions;
17
18impl<Provider> Segment<Provider> for Transactions
19where
20    Provider: StaticFileProviderFactory<Primitives: NodePrimitives<SignedTx: Value + Compact>>
21        + DBProvider
22        + BlockReader,
23{
24    fn segment(&self) -> StaticFileSegment {
25        StaticFileSegment::Transactions
26    }
27
28    /// Write transactions from database table [`tables::Transactions`] to static files with segment
29    /// [`StaticFileSegment::Transactions`] for the provided block range.
30    fn copy_to_static_files(
31        &self,
32        provider: Provider,
33        block_range: RangeInclusive<BlockNumber>,
34    ) -> ProviderResult<()> {
35        let static_file_provider = provider.static_file_provider();
36        let mut static_file_writer = static_file_provider
37            .get_writer(*block_range.start(), StaticFileSegment::Transactions)?;
38
39        for block in block_range {
40            static_file_writer.increment_block(block)?;
41
42            let block_body_indices = provider
43                .block_body_indices(block)?
44                .ok_or(ProviderError::BlockBodyIndicesNotFound(block))?;
45
46            let mut transactions_cursor = provider.tx_ref().cursor_read::<tables::Transactions<
47                <Provider::Primitives as NodePrimitives>::SignedTx,
48            >>()?;
49            let transactions_walker =
50                transactions_cursor.walk_range(block_body_indices.tx_num_range())?;
51
52            for entry in transactions_walker {
53                let (tx_number, transaction) = entry?;
54
55                static_file_writer.append_transaction(tx_number, &transaction)?;
56            }
57        }
58
59        Ok(())
60    }
61}