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
79pub 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
100pub trait ProviderNodeTypes
102where
103 Self: NodeTypesForProvider + NodeTypesWithDB,
104{
105}
106impl<T> ProviderNodeTypes for T where T: NodeTypesForProvider + NodeTypesWithDB {}
107
108pub trait NodeTypesForTree:
111 NodeTypesForProvider<Primitives = EthPrimitives> + NodeTypesWithEngine
112{
113}
114impl<T> NodeTypesForTree for T where
115 T: NodeTypesForProvider<Primitives = EthPrimitives> + NodeTypesWithEngine
116{
117}
118
119pub trait TreeNodeTypes: ProviderNodeTypes + NodeTypesForTree {}
122impl<T> TreeNodeTypes for T where T: ProviderNodeTypes + NodeTypesForTree {}
123
124pub struct BlockchainProvider<N: NodeTypesWithDB> {
130 database: ProviderFactory<N>,
132 tree: Arc<dyn TreeViewer<Primitives = N::Primitives>>,
134 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 #[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 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 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 #[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 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 let mut block = self.database.block_by_hash(hash)?;
368 if block.is_none() {
369 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 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 fn latest(&self) -> ProviderResult<StateProviderBox> {
642 trace!(target: "providers::blockchain", "Getting latest block state provider");
643 self.database.latest()
644 }
645
646 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 let hash =
658 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
659
660 self.history_by_block_hash(hash)
662 }
663 BlockNumberOrTag::Safe => {
664 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 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 if state.is_err() {
698 if let Ok(Some(pending)) = self.pending_state_by_hash(block) {
699 state = Ok(pending)
701 }
702 }
703
704 state
705 }
706
707 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 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 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 if Some(true) == hash.require_canonical {
856 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 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 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}