reth_provider/providers/
mod.rs

1use core::fmt;
2
3use crate::{
4    AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
5    BlockSource, BlockchainTreePendingStateProvider, CanonStateNotifications,
6    CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader,
7    DatabaseProviderFactory, EvmEnvProvider, FullExecutionDataProvider, HeaderProvider,
8    NodePrimitivesProvider, ProviderError, PruneCheckpointReader, ReceiptProvider,
9    ReceiptProviderIdExt, StageCheckpointReader, StateProviderBox, StateProviderFactory,
10    StaticFileProviderFactory, TransactionVariant, TransactionsProvider, TreeViewer,
11    WithdrawalsProvider,
12};
13use alloy_consensus::Header;
14use alloy_eips::{
15    eip4895::{Withdrawal, Withdrawals},
16    BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag,
17};
18use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
19use alloy_rpc_types_engine::ForkchoiceState;
20use reth_blockchain_tree_api::{
21    error::{CanonicalError, InsertBlockError},
22    BlockValidationKind, BlockchainTreeEngine, BlockchainTreeViewer, CanonicalOutcome,
23    InsertPayloadOk,
24};
25use reth_chain_state::{ChainInfoTracker, ForkChoiceNotifications, ForkChoiceSubscriptions};
26use reth_chainspec::{ChainInfo, EthereumHardforks};
27use reth_db::table::Value;
28use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
29use reth_evm::ConfigureEvmEnv;
30use reth_node_types::{
31    BlockTy, FullNodePrimitives, HeaderTy, NodeTypes, NodeTypesWithDB, NodeTypesWithEngine,
32    ReceiptTy, TxTy,
33};
34use reth_primitives::{
35    Account, BlockWithSenders, EthPrimitives, Receipt, SealedBlock, SealedBlockFor,
36    SealedBlockWithSenders, SealedHeader, TransactionMeta,
37};
38use reth_prune_types::{PruneCheckpoint, PruneSegment};
39use reth_stages_types::{StageCheckpoint, StageId};
40use reth_storage_api::{BlockBodyIndicesProvider, CanonChainTracker, OmmersProvider};
41use reth_storage_errors::provider::ProviderResult;
42use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
43use std::{
44    collections::BTreeMap,
45    ops::{RangeBounds, RangeInclusive},
46    sync::Arc,
47    time::Instant,
48};
49
50use tracing::trace;
51
52mod database;
53pub use database::*;
54
55mod static_file;
56pub use static_file::{
57    StaticFileAccess, StaticFileJarProvider, StaticFileProvider, StaticFileProviderRW,
58    StaticFileProviderRWRefMut, StaticFileWriter,
59};
60
61mod state;
62pub use state::{
63    historical::{HistoricalStateProvider, HistoricalStateProviderRef},
64    latest::{LatestStateProvider, LatestStateProviderRef},
65};
66
67mod bundle_state_provider;
68pub use bundle_state_provider::BundleStateProvider;
69
70mod consistent_view;
71pub use consistent_view::{ConsistentDbView, ConsistentViewError};
72
73mod blockchain_provider;
74pub use blockchain_provider::BlockchainProvider2;
75
76mod consistent;
77pub use consistent::ConsistentProvider;
78
79/// Helper trait to bound [`NodeTypes`] so that combined with database they satisfy
80/// [`ProviderNodeTypes`].
81pub trait NodeTypesForProvider
82where
83    Self: NodeTypes<
84        ChainSpec: EthereumHardforks,
85        Storage: ChainStorage<Self::Primitives>,
86        Primitives: FullNodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
87    >,
88{
89}
90
91impl<T> NodeTypesForProvider for T where
92    T: NodeTypes<
93        ChainSpec: EthereumHardforks,
94        Storage: ChainStorage<T::Primitives>,
95        Primitives: FullNodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
96    >
97{
98}
99
100/// Helper trait keeping common requirements of providers for [`NodeTypesWithDB`].
101pub trait ProviderNodeTypes
102where
103    Self: NodeTypesForProvider + NodeTypesWithDB,
104{
105}
106impl<T> ProviderNodeTypes for T where T: NodeTypesForProvider + NodeTypesWithDB {}
107
108/// A helper trait with requirements for [`NodeTypesForProvider`] to be used within legacy
109/// blockchain tree.
110pub trait NodeTypesForTree:
111    NodeTypesForProvider<Primitives = EthPrimitives> + NodeTypesWithEngine
112{
113}
114impl<T> NodeTypesForTree for T where
115    T: NodeTypesForProvider<Primitives = EthPrimitives> + NodeTypesWithEngine
116{
117}
118
119/// Helper trait with requirements for [`ProviderNodeTypes`] to be used within legacy blockchain
120/// tree.
121pub trait TreeNodeTypes: ProviderNodeTypes + NodeTypesForTree {}
122impl<T> TreeNodeTypes for T where T: ProviderNodeTypes + NodeTypesForTree {}
123
124/// The main type for interacting with the blockchain.
125///
126/// This type serves as the main entry point for interacting with the blockchain and provides data
127/// from database storage and from the blockchain tree (pending state etc.) It is a simple wrapper
128/// type that holds an instance of the database and the blockchain tree.
129pub struct BlockchainProvider<N: NodeTypesWithDB> {
130    /// Provider type used to access the database.
131    database: ProviderFactory<N>,
132    /// The blockchain tree instance.
133    tree: Arc<dyn TreeViewer<Primitives = N::Primitives>>,
134    /// Tracks the chain info wrt forkchoice updates
135    chain_info: ChainInfoTracker<reth_primitives::EthPrimitives>,
136}
137
138impl<N: ProviderNodeTypes> Clone for BlockchainProvider<N> {
139    fn clone(&self) -> Self {
140        Self {
141            database: self.database.clone(),
142            tree: self.tree.clone(),
143            chain_info: self.chain_info.clone(),
144        }
145    }
146}
147
148impl<N: NodeTypesWithDB> BlockchainProvider<N> {
149    /// Sets the treeviewer for the provider.
150    #[doc(hidden)]
151    pub fn with_tree(mut self, tree: Arc<dyn TreeViewer<Primitives = N::Primitives>>) -> Self {
152        self.tree = tree;
153        self
154    }
155}
156
157impl<N: TreeNodeTypes> BlockchainProvider<N> {
158    /// Create new provider instance that wraps the database and the blockchain tree, using the
159    /// provided latest header to initialize the chain info tracker, alongside the finalized header
160    /// if it exists.
161    pub fn with_blocks(
162        database: ProviderFactory<N>,
163        tree: Arc<dyn TreeViewer<Primitives = N::Primitives>>,
164        latest: SealedHeader,
165        finalized: Option<SealedHeader>,
166        safe: Option<SealedHeader>,
167    ) -> Self {
168        Self { database, tree, chain_info: ChainInfoTracker::new(latest, finalized, safe) }
169    }
170
171    /// Create a new provider using only the database and the tree, fetching the latest header from
172    /// the database to initialize the provider.
173    pub fn new(
174        database: ProviderFactory<N>,
175        tree: Arc<dyn TreeViewer<Primitives = N::Primitives>>,
176    ) -> ProviderResult<Self> {
177        let provider = database.provider()?;
178        let best = provider.chain_info()?;
179        let latest_header = provider
180            .header_by_number(best.best_number)?
181            .ok_or_else(|| ProviderError::HeaderNotFound(best.best_number.into()))?;
182
183        let finalized_header = provider
184            .last_finalized_block_number()?
185            .map(|num| provider.sealed_header(num))
186            .transpose()?
187            .flatten();
188
189        let safe_header = provider
190            .last_safe_block_number()?
191            .map(|num| provider.sealed_header(num))
192            .transpose()?
193            .flatten();
194
195        Ok(Self::with_blocks(
196            database,
197            tree,
198            SealedHeader::new(latest_header, best.best_hash),
199            finalized_header,
200            safe_header,
201        ))
202    }
203
204    /// Ensures that the given block number is canonical (synced)
205    ///
206    /// This is a helper for guarding the [`HistoricalStateProvider`] against block numbers that are
207    /// out of range and would lead to invalid results, mainly during initial sync.
208    ///
209    /// Verifying the `block_number` would be expensive since we need to lookup sync table
210    /// Instead, we ensure that the `block_number` is within the range of the
211    /// [`Self::best_block_number`] which is updated when a block is synced.
212    #[inline]
213    fn ensure_canonical_block(&self, block_number: BlockNumber) -> ProviderResult<()> {
214        let latest = self.best_block_number()?;
215        if block_number > latest {
216            Err(ProviderError::HeaderNotFound(block_number.into()))
217        } else {
218            Ok(())
219        }
220    }
221}
222
223impl<N> BlockchainProvider<N>
224where
225    Self: StateProviderFactory,
226    N: NodeTypesWithDB,
227{
228    /// Return a [`StateProviderBox`] that contains bundle state data provider.
229    /// Used to inspect or execute transaction on the pending state.
230    fn pending_with_provider(
231        &self,
232        bundle_state_data: Box<dyn FullExecutionDataProvider>,
233    ) -> ProviderResult<StateProviderBox> {
234        let canonical_fork = bundle_state_data.canonical_fork();
235        trace!(target: "providers::blockchain", ?canonical_fork, "Returning post state provider");
236
237        let state_provider = self.history_by_block_hash(canonical_fork.hash)?;
238        let bundle_state_provider = BundleStateProvider::new(state_provider, bundle_state_data);
239        Ok(Box::new(bundle_state_provider))
240    }
241}
242
243impl<N: ProviderNodeTypes> NodePrimitivesProvider for BlockchainProvider<N> {
244    type Primitives = N::Primitives;
245}
246
247impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider<N> {
248    type DB = N::DB;
249    type Provider = <ProviderFactory<N> as DatabaseProviderFactory>::Provider;
250    type ProviderRW = <ProviderFactory<N> as DatabaseProviderFactory>::ProviderRW;
251
252    fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
253        self.database.database_provider_ro()
254    }
255
256    fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
257        self.database.database_provider_rw()
258    }
259}
260
261impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider<N> {
262    fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
263        self.database.static_file_provider()
264    }
265}
266
267impl<N: TreeNodeTypes> HeaderProvider for BlockchainProvider<N> {
268    type Header = Header;
269
270    fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
271        self.database.header(block_hash)
272    }
273
274    fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
275        self.database.header_by_number(num)
276    }
277
278    fn header_td(&self, hash: &BlockHash) -> ProviderResult<Option<U256>> {
279        self.database.header_td(hash)
280    }
281
282    fn header_td_by_number(&self, number: BlockNumber) -> ProviderResult<Option<U256>> {
283        self.database.header_td_by_number(number)
284    }
285
286    fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
287        self.database.headers_range(range)
288    }
289
290    fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
291        self.database.sealed_header(number)
292    }
293
294    fn sealed_headers_range(
295        &self,
296        range: impl RangeBounds<BlockNumber>,
297    ) -> ProviderResult<Vec<SealedHeader>> {
298        self.database.sealed_headers_range(range)
299    }
300
301    fn sealed_headers_while(
302        &self,
303        range: impl RangeBounds<BlockNumber>,
304        predicate: impl FnMut(&SealedHeader) -> bool,
305    ) -> ProviderResult<Vec<SealedHeader>> {
306        self.database.sealed_headers_while(range, predicate)
307    }
308}
309
310impl<N: ProviderNodeTypes> BlockHashReader for BlockchainProvider<N> {
311    fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
312        self.database.block_hash(number)
313    }
314
315    fn canonical_hashes_range(
316        &self,
317        start: BlockNumber,
318        end: BlockNumber,
319    ) -> ProviderResult<Vec<B256>> {
320        self.database.canonical_hashes_range(start, end)
321    }
322}
323
324impl<N: ProviderNodeTypes> BlockNumReader for BlockchainProvider<N> {
325    fn chain_info(&self) -> ProviderResult<ChainInfo> {
326        Ok(self.chain_info.chain_info())
327    }
328
329    fn best_block_number(&self) -> ProviderResult<BlockNumber> {
330        Ok(self.chain_info.get_canonical_block_number())
331    }
332
333    fn last_block_number(&self) -> ProviderResult<BlockNumber> {
334        self.database.last_block_number()
335    }
336
337    fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
338        self.database.block_number(hash)
339    }
340}
341
342impl<N: ProviderNodeTypes> BlockIdReader for BlockchainProvider<N> {
343    fn pending_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
344        Ok(self.tree.pending_block_num_hash())
345    }
346
347    fn safe_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
348        Ok(self.chain_info.get_safe_num_hash())
349    }
350
351    fn finalized_block_num_hash(&self) -> ProviderResult<Option<BlockNumHash>> {
352        Ok(self.chain_info.get_finalized_num_hash())
353    }
354}
355
356impl<N: TreeNodeTypes> BlockReader for BlockchainProvider<N> {
357    type Block = BlockTy<N>;
358
359    fn find_block_by_hash(
360        &self,
361        hash: B256,
362        source: BlockSource,
363    ) -> ProviderResult<Option<Self::Block>> {
364        let block = match source {
365            BlockSource::Any => {
366                // check database first
367                let mut block = self.database.block_by_hash(hash)?;
368                if block.is_none() {
369                    // Note: it's fine to return the unsealed block because the caller already has
370                    // the hash
371                    block = self.tree.block_by_hash(hash).map(|block| block.unseal());
372                }
373                block
374            }
375            BlockSource::Pending => self.tree.block_by_hash(hash).map(|block| block.unseal()),
376            BlockSource::Canonical => self.database.block_by_hash(hash)?,
377        };
378
379        Ok(block)
380    }
381
382    fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
383        match id {
384            BlockHashOrNumber::Hash(hash) => self.find_block_by_hash(hash, BlockSource::Any),
385            BlockHashOrNumber::Number(num) => self.database.block_by_number(num),
386        }
387    }
388
389    fn pending_block(&self) -> ProviderResult<Option<SealedBlockFor<Self::Block>>> {
390        Ok(self.tree.pending_block())
391    }
392
393    fn pending_block_with_senders(
394        &self,
395    ) -> ProviderResult<Option<SealedBlockWithSenders<Self::Block>>> {
396        Ok(self.tree.pending_block_with_senders())
397    }
398
399    fn pending_block_and_receipts(
400        &self,
401    ) -> ProviderResult<Option<(SealedBlockFor<Self::Block>, Vec<Receipt>)>> {
402        Ok(self.tree.pending_block_and_receipts())
403    }
404
405    /// Returns the block with senders with matching number or hash from database.
406    ///
407    /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid
408    /// hashes, since they would need to be calculated on the spot, and we want fast querying.**
409    ///
410    /// Returns `None` if block is not found.
411    fn block_with_senders(
412        &self,
413        id: BlockHashOrNumber,
414        transaction_kind: TransactionVariant,
415    ) -> ProviderResult<Option<BlockWithSenders<Self::Block>>> {
416        self.database.block_with_senders(id, transaction_kind)
417    }
418
419    fn sealed_block_with_senders(
420        &self,
421        id: BlockHashOrNumber,
422        transaction_kind: TransactionVariant,
423    ) -> ProviderResult<Option<SealedBlockWithSenders<Self::Block>>> {
424        self.database.sealed_block_with_senders(id, transaction_kind)
425    }
426
427    fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
428        self.database.block_range(range)
429    }
430
431    fn block_with_senders_range(
432        &self,
433        range: RangeInclusive<BlockNumber>,
434    ) -> ProviderResult<Vec<BlockWithSenders<Self::Block>>> {
435        self.database.block_with_senders_range(range)
436    }
437
438    fn sealed_block_with_senders_range(
439        &self,
440        range: RangeInclusive<BlockNumber>,
441    ) -> ProviderResult<Vec<SealedBlockWithSenders<Self::Block>>> {
442        self.database.sealed_block_with_senders_range(range)
443    }
444}
445
446impl<N: ProviderNodeTypes> TransactionsProvider for BlockchainProvider<N> {
447    type Transaction = TxTy<N>;
448
449    fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
450        self.database.transaction_id(tx_hash)
451    }
452
453    fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
454        self.database.transaction_by_id(id)
455    }
456
457    fn transaction_by_id_unhashed(
458        &self,
459        id: TxNumber,
460    ) -> ProviderResult<Option<Self::Transaction>> {
461        self.database.transaction_by_id_unhashed(id)
462    }
463
464    fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
465        self.database.transaction_by_hash(hash)
466    }
467
468    fn transaction_by_hash_with_meta(
469        &self,
470        tx_hash: TxHash,
471    ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
472        self.database.transaction_by_hash_with_meta(tx_hash)
473    }
474
475    fn transaction_block(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
476        self.database.transaction_block(id)
477    }
478
479    fn transactions_by_block(
480        &self,
481        id: BlockHashOrNumber,
482    ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
483        self.database.transactions_by_block(id)
484    }
485
486    fn transactions_by_block_range(
487        &self,
488        range: impl RangeBounds<BlockNumber>,
489    ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
490        self.database.transactions_by_block_range(range)
491    }
492
493    fn transactions_by_tx_range(
494        &self,
495        range: impl RangeBounds<TxNumber>,
496    ) -> ProviderResult<Vec<Self::Transaction>> {
497        self.database.transactions_by_tx_range(range)
498    }
499
500    fn senders_by_tx_range(
501        &self,
502        range: impl RangeBounds<TxNumber>,
503    ) -> ProviderResult<Vec<Address>> {
504        self.database.senders_by_tx_range(range)
505    }
506
507    fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>> {
508        self.database.transaction_sender(id)
509    }
510}
511
512impl<N: ProviderNodeTypes> ReceiptProvider for BlockchainProvider<N> {
513    type Receipt = ReceiptTy<N>;
514
515    fn receipt(&self, id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
516        self.database.receipt(id)
517    }
518
519    fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
520        self.database.receipt_by_hash(hash)
521    }
522
523    fn receipts_by_block(
524        &self,
525        block: BlockHashOrNumber,
526    ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
527        self.database.receipts_by_block(block)
528    }
529
530    fn receipts_by_tx_range(
531        &self,
532        range: impl RangeBounds<TxNumber>,
533    ) -> ProviderResult<Vec<Self::Receipt>> {
534        self.database.receipts_by_tx_range(range)
535    }
536}
537
538impl<N: TreeNodeTypes> ReceiptProviderIdExt for BlockchainProvider<N> {
539    fn receipts_by_block_id(&self, block: BlockId) -> ProviderResult<Option<Vec<Receipt>>> {
540        match block {
541            BlockId::Hash(rpc_block_hash) => {
542                let mut receipts = self.receipts_by_block(rpc_block_hash.block_hash.into())?;
543                if receipts.is_none() && !rpc_block_hash.require_canonical.unwrap_or(false) {
544                    receipts = self.tree.receipts_by_block_hash(rpc_block_hash.block_hash);
545                }
546                Ok(receipts)
547            }
548            BlockId::Number(num_tag) => match num_tag {
549                BlockNumberOrTag::Pending => Ok(self.tree.pending_receipts()),
550                _ => {
551                    if let Some(num) = self.convert_block_number(num_tag)? {
552                        self.receipts_by_block(num.into())
553                    } else {
554                        Ok(None)
555                    }
556                }
557            },
558        }
559    }
560}
561
562impl<N: ProviderNodeTypes> WithdrawalsProvider for BlockchainProvider<N> {
563    fn withdrawals_by_block(
564        &self,
565        id: BlockHashOrNumber,
566        timestamp: u64,
567    ) -> ProviderResult<Option<Withdrawals>> {
568        self.database.withdrawals_by_block(id, timestamp)
569    }
570
571    fn latest_withdrawal(&self) -> ProviderResult<Option<Withdrawal>> {
572        self.database.latest_withdrawal()
573    }
574}
575
576impl<N: TreeNodeTypes> OmmersProvider for BlockchainProvider<N> {
577    fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
578        self.database.ommers(id)
579    }
580}
581
582impl<N: ProviderNodeTypes> BlockBodyIndicesProvider for BlockchainProvider<N> {
583    fn block_body_indices(
584        &self,
585        number: BlockNumber,
586    ) -> ProviderResult<Option<StoredBlockBodyIndices>> {
587        self.database.block_body_indices(number)
588    }
589}
590
591impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider<N> {
592    fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
593        self.database.provider()?.get_stage_checkpoint(id)
594    }
595
596    fn get_stage_checkpoint_progress(&self, id: StageId) -> ProviderResult<Option<Vec<u8>>> {
597        self.database.provider()?.get_stage_checkpoint_progress(id)
598    }
599
600    fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
601        self.database.provider()?.get_all_checkpoints()
602    }
603}
604
605impl<N: TreeNodeTypes> EvmEnvProvider for BlockchainProvider<N> {
606    fn env_with_header<EvmConfig>(
607        &self,
608        header: &Header,
609        evm_config: EvmConfig,
610    ) -> ProviderResult<(CfgEnvWithHandlerCfg, BlockEnv)>
611    where
612        EvmConfig: ConfigureEvmEnv<Header = Header>,
613    {
614        self.database.provider()?.env_with_header(header, evm_config)
615    }
616}
617
618impl<N: ProviderNodeTypes> PruneCheckpointReader for BlockchainProvider<N> {
619    fn get_prune_checkpoint(
620        &self,
621        segment: PruneSegment,
622    ) -> ProviderResult<Option<PruneCheckpoint>> {
623        self.database.provider()?.get_prune_checkpoint(segment)
624    }
625
626    fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
627        self.database.provider()?.get_prune_checkpoints()
628    }
629}
630
631impl<N: ProviderNodeTypes> ChainSpecProvider for BlockchainProvider<N> {
632    type ChainSpec = N::ChainSpec;
633
634    fn chain_spec(&self) -> Arc<Self::ChainSpec> {
635        self.database.chain_spec()
636    }
637}
638
639impl<N: TreeNodeTypes> StateProviderFactory for BlockchainProvider<N> {
640    /// Storage provider for latest block
641    fn latest(&self) -> ProviderResult<StateProviderBox> {
642        trace!(target: "providers::blockchain", "Getting latest block state provider");
643        self.database.latest()
644    }
645
646    /// Returns a [`StateProviderBox`] indexed by the given block number or tag.
647    ///
648    /// Note: if a number is provided this will only look at historical(canonical) state.
649    fn state_by_block_number_or_tag(
650        &self,
651        number_or_tag: BlockNumberOrTag,
652    ) -> ProviderResult<StateProviderBox> {
653        match number_or_tag {
654            BlockNumberOrTag::Latest => self.latest(),
655            BlockNumberOrTag::Finalized => {
656                // we can only get the finalized state by hash, not by num
657                let hash =
658                    self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
659
660                // only look at historical state
661                self.history_by_block_hash(hash)
662            }
663            BlockNumberOrTag::Safe => {
664                // we can only get the safe state by hash, not by num
665                let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
666
667                self.history_by_block_hash(hash)
668            }
669            BlockNumberOrTag::Earliest => self.history_by_block_number(0),
670            BlockNumberOrTag::Pending => self.pending(),
671            BlockNumberOrTag::Number(num) => {
672                // Note: The `BlockchainProvider` could also lookup the tree for the given block number, if for example the block number is `latest + 1`, however this should only support canonical state: <https://github.com/paradigmxyz/reth/issues/4515>
673                self.history_by_block_number(num)
674            }
675        }
676    }
677
678    fn history_by_block_number(
679        &self,
680        block_number: BlockNumber,
681    ) -> ProviderResult<StateProviderBox> {
682        trace!(target: "providers::blockchain", ?block_number, "Getting history by block number");
683        self.ensure_canonical_block(block_number)?;
684        self.database.history_by_block_number(block_number)
685    }
686
687    fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
688        trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
689        self.database.history_by_block_hash(block_hash)
690    }
691
692    fn state_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox> {
693        trace!(target: "providers::blockchain", ?block, "Getting state by block hash");
694        let mut state = self.history_by_block_hash(block);
695
696        // we failed to get the state by hash, from disk, hash block be the pending block
697        if state.is_err() {
698            if let Ok(Some(pending)) = self.pending_state_by_hash(block) {
699                // we found pending block by hash
700                state = Ok(pending)
701            }
702        }
703
704        state
705    }
706
707    /// Returns the state provider for pending state.
708    ///
709    /// If there's no pending block available then the latest state provider is returned:
710    /// [`Self::latest`]
711    fn pending(&self) -> ProviderResult<StateProviderBox> {
712        trace!(target: "providers::blockchain", "Getting provider for pending state");
713
714        if let Some(block) = self.tree.pending_block_num_hash() {
715            if let Ok(pending) = self.tree.pending_state_provider(block.hash) {
716                return self.pending_with_provider(pending)
717            }
718        }
719
720        // fallback to latest state if the pending block is not available
721        self.latest()
722    }
723
724    fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
725        if let Some(state) = self.tree.find_pending_state_provider(block_hash) {
726            return Ok(Some(self.pending_with_provider(state)?))
727        }
728        Ok(None)
729    }
730}
731
732impl<N: ProviderNodeTypes> BlockchainTreeEngine for BlockchainProvider<N> {
733    fn buffer_block(&self, block: SealedBlockWithSenders) -> Result<(), InsertBlockError> {
734        self.tree.buffer_block(block)
735    }
736
737    fn insert_block(
738        &self,
739        block: SealedBlockWithSenders,
740        validation_kind: BlockValidationKind,
741    ) -> Result<InsertPayloadOk, InsertBlockError> {
742        self.tree.insert_block(block, validation_kind)
743    }
744
745    fn finalize_block(&self, finalized_block: BlockNumber) -> ProviderResult<()> {
746        self.tree.finalize_block(finalized_block)
747    }
748
749    fn connect_buffered_blocks_to_canonical_hashes_and_finalize(
750        &self,
751        last_finalized_block: BlockNumber,
752    ) -> Result<(), CanonicalError> {
753        self.tree.connect_buffered_blocks_to_canonical_hashes_and_finalize(last_finalized_block)
754    }
755
756    fn update_block_hashes_and_clear_buffered(
757        &self,
758    ) -> Result<BTreeMap<BlockNumber, B256>, CanonicalError> {
759        self.tree.update_block_hashes_and_clear_buffered()
760    }
761
762    fn connect_buffered_blocks_to_canonical_hashes(&self) -> Result<(), CanonicalError> {
763        self.tree.connect_buffered_blocks_to_canonical_hashes()
764    }
765
766    fn make_canonical(&self, block_hash: BlockHash) -> Result<CanonicalOutcome, CanonicalError> {
767        self.tree.make_canonical(block_hash)
768    }
769}
770
771impl<N: ProviderNodeTypes> BlockchainTreeViewer for BlockchainProvider<N> {
772    fn header_by_hash(&self, hash: BlockHash) -> Option<SealedHeader> {
773        self.tree.header_by_hash(hash)
774    }
775
776    fn block_by_hash(&self, block_hash: BlockHash) -> Option<SealedBlock> {
777        self.tree.block_by_hash(block_hash)
778    }
779
780    fn block_with_senders_by_hash(&self, block_hash: BlockHash) -> Option<SealedBlockWithSenders> {
781        self.tree.block_with_senders_by_hash(block_hash)
782    }
783
784    fn buffered_header_by_hash(&self, block_hash: BlockHash) -> Option<SealedHeader> {
785        self.tree.buffered_header_by_hash(block_hash)
786    }
787
788    fn is_canonical(&self, hash: BlockHash) -> Result<bool, ProviderError> {
789        self.tree.is_canonical(hash)
790    }
791
792    fn lowest_buffered_ancestor(&self, hash: BlockHash) -> Option<SealedBlockWithSenders> {
793        self.tree.lowest_buffered_ancestor(hash)
794    }
795
796    fn canonical_tip(&self) -> BlockNumHash {
797        self.tree.canonical_tip()
798    }
799
800    fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
801        self.tree.pending_block_num_hash()
802    }
803
804    fn pending_block_and_receipts(&self) -> Option<(SealedBlock, Vec<Receipt>)> {
805        self.tree.pending_block_and_receipts()
806    }
807
808    fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<Receipt>> {
809        self.tree.receipts_by_block_hash(block_hash)
810    }
811}
812
813impl<N: TreeNodeTypes> CanonChainTracker for BlockchainProvider<N> {
814    type Header = HeaderTy<N>;
815
816    fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
817        // update timestamp
818        self.chain_info.on_forkchoice_update_received();
819    }
820
821    fn last_received_update_timestamp(&self) -> Option<Instant> {
822        self.chain_info.last_forkchoice_update_received_at()
823    }
824
825    fn on_transition_configuration_exchanged(&self) {
826        self.chain_info.on_transition_configuration_exchanged();
827    }
828
829    fn last_exchanged_transition_configuration_timestamp(&self) -> Option<Instant> {
830        self.chain_info.last_transition_configuration_exchanged_at()
831    }
832
833    fn set_canonical_head(&self, header: SealedHeader) {
834        self.chain_info.set_canonical_head(header);
835    }
836
837    fn set_safe(&self, header: SealedHeader) {
838        self.chain_info.set_safe(header);
839    }
840
841    fn set_finalized(&self, header: SealedHeader) {
842        self.chain_info.set_finalized(header);
843    }
844}
845
846impl<N: TreeNodeTypes> BlockReaderIdExt for BlockchainProvider<N> {
847    fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
848        match id {
849            BlockId::Number(num) => self.block_by_number_or_tag(num),
850            BlockId::Hash(hash) => {
851                // TODO: should we only apply this for the RPCs that are listed in EIP-1898?
852                // so not at the provider level?
853                // if we decide to do this at a higher level, then we can make this an automatic
854                // trait impl
855                if Some(true) == hash.require_canonical {
856                    // check the database, canonical blocks are only stored in the database
857                    self.find_block_by_hash(hash.block_hash, BlockSource::Canonical)
858                } else {
859                    BlockReader::block_by_hash(self, hash.block_hash)
860                }
861            }
862        }
863    }
864
865    fn header_by_number_or_tag(
866        &self,
867        id: BlockNumberOrTag,
868    ) -> ProviderResult<Option<Self::Header>> {
869        Ok(match id {
870            BlockNumberOrTag::Latest => Some(self.chain_info.get_canonical_head().unseal()),
871            BlockNumberOrTag::Finalized => {
872                self.chain_info.get_finalized_header().map(|h| h.unseal())
873            }
874            BlockNumberOrTag::Safe => self.chain_info.get_safe_header().map(|h| h.unseal()),
875            BlockNumberOrTag::Earliest => self.header_by_number(0)?,
876            BlockNumberOrTag::Pending => self.tree.pending_header().map(|h| h.unseal()),
877            BlockNumberOrTag::Number(num) => self.header_by_number(num)?,
878        })
879    }
880
881    fn sealed_header_by_number_or_tag(
882        &self,
883        id: BlockNumberOrTag,
884    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
885        match id {
886            BlockNumberOrTag::Latest => Ok(Some(self.chain_info.get_canonical_head())),
887            BlockNumberOrTag::Finalized => Ok(self.chain_info.get_finalized_header()),
888            BlockNumberOrTag::Safe => Ok(self.chain_info.get_safe_header()),
889            BlockNumberOrTag::Earliest => self
890                .header_by_number(0)?
891                .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal(h)))),
892            BlockNumberOrTag::Pending => Ok(self.tree.pending_header()),
893            BlockNumberOrTag::Number(num) => self
894                .header_by_number(num)?
895                .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal(h)))),
896        }
897    }
898
899    fn sealed_header_by_id(
900        &self,
901        id: BlockId,
902    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
903        Ok(match id {
904            BlockId::Number(num) => self.sealed_header_by_number_or_tag(num)?,
905            BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(SealedHeader::seal),
906        })
907    }
908
909    fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
910        Ok(match id {
911            BlockId::Number(num) => self.header_by_number_or_tag(num)?,
912            BlockId::Hash(hash) => self.header(&hash.block_hash)?,
913        })
914    }
915
916    fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>> {
917        match id {
918            BlockId::Number(num) => self.ommers_by_number_or_tag(num),
919            BlockId::Hash(hash) => {
920                // TODO: EIP-1898 question, see above
921                // here it is not handled
922                self.ommers(BlockHashOrNumber::Hash(hash.block_hash))
923            }
924        }
925    }
926}
927
928impl<N: ProviderNodeTypes> BlockchainTreePendingStateProvider for BlockchainProvider<N> {
929    fn find_pending_state_provider(
930        &self,
931        block_hash: BlockHash,
932    ) -> Option<Box<dyn FullExecutionDataProvider>> {
933        self.tree.find_pending_state_provider(block_hash)
934    }
935}
936
937impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
938    fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<Self::Primitives> {
939        self.tree.subscribe_to_canonical_state()
940    }
941}
942
943impl<N: TreeNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
944    type Header = HeaderTy<N>;
945
946    fn subscribe_safe_block(&self) -> ForkChoiceNotifications {
947        let receiver = self.chain_info.subscribe_safe_block();
948        ForkChoiceNotifications(receiver)
949    }
950
951    fn subscribe_finalized_block(&self) -> ForkChoiceNotifications {
952        let receiver = self.chain_info.subscribe_finalized_block();
953        ForkChoiceNotifications(receiver)
954    }
955}
956
957impl<N: ProviderNodeTypes> ChangeSetReader for BlockchainProvider<N> {
958    fn account_block_changeset(
959        &self,
960        block_number: BlockNumber,
961    ) -> ProviderResult<Vec<AccountBeforeTx>> {
962        self.database.provider()?.account_block_changeset(block_number)
963    }
964}
965
966impl<N: ProviderNodeTypes> AccountReader for BlockchainProvider<N> {
967    /// Get basic account information.
968    fn basic_account(&self, address: Address) -> ProviderResult<Option<Account>> {
969        self.database.provider()?.basic_account(address)
970    }
971}
972
973impl<N: NodeTypesWithDB> fmt::Debug for BlockchainProvider<N> {
974    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
975        f.debug_struct("BlockchainProvider").finish_non_exhaustive()
976    }
977}