reth_blockchain_tree/
externals.rsuse alloy_primitives::{BlockHash, BlockNumber};
use reth_consensus::FullConsensus;
use reth_db::{static_file::BlockHashMask, tables};
use reth_db_api::{cursor::DbCursorRO, transaction::DbTx};
use reth_node_types::NodeTypesWithDB;
use reth_primitives::StaticFileSegment;
use reth_provider::{
providers::ProviderNodeTypes, ChainStateBlockReader, ChainStateBlockWriter, ProviderFactory,
StaticFileProviderFactory, StatsReader,
};
use reth_storage_errors::provider::ProviderResult;
use std::{collections::BTreeMap, sync::Arc};
pub use reth_provider::providers::{NodeTypesForTree, TreeNodeTypes};
#[derive(Debug)]
pub struct TreeExternals<N: NodeTypesWithDB, E> {
pub(crate) provider_factory: ProviderFactory<N>,
pub(crate) consensus: Arc<dyn FullConsensus>,
pub(crate) executor_factory: E,
}
impl<N: ProviderNodeTypes, E> TreeExternals<N, E> {
pub fn new(
provider_factory: ProviderFactory<N>,
consensus: Arc<dyn FullConsensus>,
executor_factory: E,
) -> Self {
Self { provider_factory, consensus, executor_factory }
}
}
impl<N: ProviderNodeTypes, E> TreeExternals<N, E> {
pub(crate) fn fetch_latest_canonical_hashes(
&self,
num_hashes: usize,
) -> ProviderResult<BTreeMap<BlockNumber, BlockHash>> {
let mut hashes = self
.provider_factory
.provider()?
.tx_ref()
.cursor_read::<tables::CanonicalHeaders>()?
.walk_back(None)?
.take(num_hashes)
.collect::<Result<BTreeMap<BlockNumber, BlockHash>, _>>()?;
let static_file_provider = self.provider_factory.static_file_provider();
let total_headers = static_file_provider.count_entries::<tables::Headers>()? as u64;
if total_headers > 0 {
let range =
total_headers.saturating_sub(1).saturating_sub(num_hashes as u64)..total_headers;
hashes.extend(range.clone().zip(static_file_provider.fetch_range_with_predicate(
StaticFileSegment::Headers,
range,
|cursor, number| cursor.get_one::<BlockHashMask>(number.into()),
|_| true,
)?));
}
let hashes = hashes.into_iter().rev().take(num_hashes).collect();
Ok(hashes)
}
pub(crate) fn fetch_latest_finalized_block_number(
&self,
) -> ProviderResult<Option<BlockNumber>> {
self.provider_factory.provider()?.last_finalized_block_number()
}
pub(crate) fn save_finalized_block_number(
&self,
block_number: BlockNumber,
) -> ProviderResult<()> {
let provider_rw = self.provider_factory.provider_rw()?;
provider_rw.save_finalized_block_number(block_number)?;
provider_rw.commit()?;
Ok(())
}
}