reth_static_file/segments/
transactions.rs

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