reth_blockchain_tree/
externals.rs1use alloy_primitives::{BlockHash, BlockNumber};
4use reth_consensus::FullConsensus;
5use reth_db::{static_file::BlockHashMask, tables};
6use reth_db_api::{cursor::DbCursorRO, transaction::DbTx};
7use reth_node_types::NodeTypesWithDB;
8use reth_primitives::StaticFileSegment;
9use reth_provider::{
10 providers::ProviderNodeTypes, ChainStateBlockReader, ChainStateBlockWriter, ProviderFactory,
11 StaticFileProviderFactory, StatsReader,
12};
13use reth_storage_errors::provider::ProviderResult;
14use std::{collections::BTreeMap, sync::Arc};
15
16pub use reth_provider::providers::{NodeTypesForTree, TreeNodeTypes};
17
18#[derive(Debug)]
27pub struct TreeExternals<N: NodeTypesWithDB, E> {
28 pub(crate) provider_factory: ProviderFactory<N>,
30 pub(crate) consensus: Arc<dyn FullConsensus>,
32 pub(crate) executor_factory: E,
34}
35
36impl<N: ProviderNodeTypes, E> TreeExternals<N, E> {
37 pub fn new(
39 provider_factory: ProviderFactory<N>,
40 consensus: Arc<dyn FullConsensus>,
41 executor_factory: E,
42 ) -> Self {
43 Self { provider_factory, consensus, executor_factory }
44 }
45}
46
47impl<N: ProviderNodeTypes, E> TreeExternals<N, E> {
48 pub(crate) fn fetch_latest_canonical_hashes(
52 &self,
53 num_hashes: usize,
54 ) -> ProviderResult<BTreeMap<BlockNumber, BlockHash>> {
55 let mut hashes = self
57 .provider_factory
58 .provider()?
59 .tx_ref()
60 .cursor_read::<tables::CanonicalHeaders>()?
61 .walk_back(None)?
62 .take(num_hashes)
63 .collect::<Result<BTreeMap<BlockNumber, BlockHash>, _>>()?;
64
65 let static_file_provider = self.provider_factory.static_file_provider();
72 let total_headers = static_file_provider.count_entries::<tables::Headers>()? as u64;
73 if total_headers > 0 {
74 let range =
75 total_headers.saturating_sub(1).saturating_sub(num_hashes as u64)..total_headers;
76
77 hashes.extend(range.clone().zip(static_file_provider.fetch_range_with_predicate(
78 StaticFileSegment::Headers,
79 range,
80 |cursor, number| cursor.get_one::<BlockHashMask>(number.into()),
81 |_| true,
82 )?));
83 }
84
85 let hashes = hashes.into_iter().rev().take(num_hashes).collect();
88 Ok(hashes)
89 }
90
91 pub(crate) fn fetch_latest_finalized_block_number(
92 &self,
93 ) -> ProviderResult<Option<BlockNumber>> {
94 self.provider_factory.provider()?.last_finalized_block_number()
95 }
96
97 pub(crate) fn save_finalized_block_number(
98 &self,
99 block_number: BlockNumber,
100 ) -> ProviderResult<()> {
101 let provider_rw = self.provider_factory.provider_rw()?;
102 provider_rw.save_finalized_block_number(block_number)?;
103 provider_rw.commit()?;
104 Ok(())
105 }
106}