reth_static_file/segments/
headers.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::{providers::StaticFileWriter, DBProvider, StaticFileProviderFactory};
8use reth_static_file_types::StaticFileSegment;
9use reth_storage_errors::provider::ProviderResult;
10use std::ops::RangeInclusive;
11
12/// Static File segment responsible for [`StaticFileSegment::Headers`] part of data.
13#[derive(Debug, Default)]
14pub struct Headers;
15
16impl<Provider> Segment<Provider> for Headers
17where
18    Provider: StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact + Value>>
19        + DBProvider,
20{
21    fn segment(&self) -> StaticFileSegment {
22        StaticFileSegment::Headers
23    }
24
25    fn copy_to_static_files(
26        &self,
27        provider: Provider,
28        block_range: RangeInclusive<BlockNumber>,
29    ) -> ProviderResult<()> {
30        let static_file_provider = provider.static_file_provider();
31        let mut static_file_writer =
32            static_file_provider.get_writer(*block_range.start(), StaticFileSegment::Headers)?;
33
34        let mut headers_cursor = provider
35            .tx_ref()
36            .cursor_read::<tables::Headers<<Provider::Primitives as NodePrimitives>::BlockHeader>>(
37            )?;
38        let headers_walker = headers_cursor.walk_range(block_range.clone())?;
39
40        let mut header_td_cursor =
41            provider.tx_ref().cursor_read::<tables::HeaderTerminalDifficulties>()?;
42        let header_td_walker = header_td_cursor.walk_range(block_range.clone())?;
43
44        let mut canonical_headers_cursor =
45            provider.tx_ref().cursor_read::<tables::CanonicalHeaders>()?;
46        let canonical_headers_walker = canonical_headers_cursor.walk_range(block_range)?;
47
48        for ((header_entry, header_td_entry), canonical_header_entry) in
49            headers_walker.zip(header_td_walker).zip(canonical_headers_walker)
50        {
51            let (header_block, header) = header_entry?;
52            let (header_td_block, header_td) = header_td_entry?;
53            let (canonical_header_block, canonical_header) = canonical_header_entry?;
54
55            debug_assert_eq!(header_block, header_td_block);
56            debug_assert_eq!(header_td_block, canonical_header_block);
57
58            static_file_writer.append_header(&header, header_td.0, &canonical_header)?;
59        }
60
61        Ok(())
62    }
63}