1#![doc(
20 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
21 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
22 issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
23)]
24#![cfg_attr(not(test), warn(unused_crate_dependencies))]
25#![cfg_attr(docsrs, feature(doc_cfg))]
26
27use alloy_consensus::{constants::KECCAK_EMPTY, BlockHeader};
28use alloy_eips::{BlockHashOrNumber, BlockNumberOrTag};
29use alloy_network::{primitives::HeaderResponse, BlockResponse};
30use alloy_primitives::{Address, BlockHash, BlockNumber, StorageKey, TxHash, TxNumber, B256, U256};
31use alloy_provider::{ext::DebugApi, network::Network, Provider};
32use alloy_rpc_types::{AccountInfo, BlockId};
33use alloy_rpc_types_engine::ForkchoiceState;
34use dashmap::DashMap;
35use reth_chainspec::{ChainInfo, ChainSpecProvider};
36use reth_db_api::{
37 mock::{DatabaseMock, TxMock},
38 models::StoredBlockBodyIndices,
39};
40use reth_errors::{ProviderError, ProviderResult};
41use reth_node_types::{
42 Block, BlockBody, BlockTy, HeaderTy, NodeTypes, PrimitivesTy, ReceiptTy, TxTy,
43};
44use reth_primitives::{Account, Bytecode, RecoveredBlock, SealedHeader, TransactionMeta};
45use reth_provider::{
46 AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BytecodeReader,
47 CanonChainTracker, CanonStateNotification, CanonStateNotifications, CanonStateSubscriptions,
48 ChainStateBlockReader, ChainStateBlockWriter, ChangeSetReader, DatabaseProviderFactory,
49 HeaderProvider, PruneCheckpointReader, ReceiptProvider, StageCheckpointReader, StateProvider,
50 StateProviderBox, StateProviderFactory, StateReader, StateRootProvider, StorageReader,
51 TransactionVariant, TransactionsProvider,
52};
53use reth_prune_types::{PruneCheckpoint, PruneSegment};
54use reth_rpc_convert::{TryFromBlockResponse, TryFromReceiptResponse, TryFromTransactionResponse};
55use reth_stages_types::{StageCheckpoint, StageId};
56use reth_storage_api::{
57 BlockBodyIndicesProvider, BlockReaderIdExt, BlockSource, DBProvider, NodePrimitivesProvider,
58 ReceiptProviderIdExt, StatsReader,
59};
60use reth_trie::{updates::TrieUpdates, AccountProof, HashedPostState, MultiProof, TrieInput};
61use std::{
62 collections::BTreeMap,
63 future::{Future, IntoFuture},
64 ops::{RangeBounds, RangeInclusive},
65 sync::Arc,
66};
67use tokio::{runtime::Handle, sync::broadcast};
68use tracing::{trace, warn};
69
70#[derive(Debug, Clone)]
72pub struct RpcBlockchainProviderConfig {
73 pub compute_state_root: bool,
75 pub reth_rpc_support: bool,
81}
82
83impl Default for RpcBlockchainProviderConfig {
84 fn default() -> Self {
85 Self { compute_state_root: false, reth_rpc_support: true }
86 }
87}
88
89impl RpcBlockchainProviderConfig {
90 pub const fn with_compute_state_root(mut self, compute: bool) -> Self {
92 self.compute_state_root = compute;
93 self
94 }
95
96 pub const fn with_reth_rpc_support(mut self, support: bool) -> Self {
98 self.reth_rpc_support = support;
99 self
100 }
101}
102
103#[derive(Clone)]
119pub struct RpcBlockchainProvider<P, Node, N = alloy_network::AnyNetwork>
120where
121 Node: NodeTypes,
122{
123 provider: P,
125 node_types: std::marker::PhantomData<Node>,
127 network: std::marker::PhantomData<N>,
129 canon_state_notification: broadcast::Sender<CanonStateNotification<PrimitivesTy<Node>>>,
131 config: RpcBlockchainProviderConfig,
133 chain_spec: Arc<Node::ChainSpec>,
135}
136
137impl<P, Node: NodeTypes, N> std::fmt::Debug for RpcBlockchainProvider<P, Node, N> {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 f.debug_struct("RpcBlockchainProvider").field("config", &self.config).finish()
140 }
141}
142
143impl<P, Node: NodeTypes, N> RpcBlockchainProvider<P, Node, N> {
144 pub fn new(provider: P) -> Self
146 where
147 Node::ChainSpec: Default,
148 {
149 Self::new_with_config(provider, RpcBlockchainProviderConfig::default())
150 }
151
152 pub fn new_with_config(provider: P, config: RpcBlockchainProviderConfig) -> Self
154 where
155 Node::ChainSpec: Default,
156 {
157 let (canon_state_notification, _) = broadcast::channel(1);
158 Self {
159 provider,
160 node_types: std::marker::PhantomData,
161 network: std::marker::PhantomData,
162 canon_state_notification,
163 config,
164 chain_spec: Arc::new(Node::ChainSpec::default()),
165 }
166 }
167
168 pub fn with_chain_spec(self, chain_spec: Arc<Node::ChainSpec>) -> Self {
170 Self {
171 provider: self.provider,
172 node_types: std::marker::PhantomData,
173 network: std::marker::PhantomData,
174 canon_state_notification: self.canon_state_notification,
175 config: self.config,
176 chain_spec,
177 }
178 }
179
180 fn block_on_async<F, T>(&self, fut: F) -> T
182 where
183 F: Future<Output = T>,
184 {
185 tokio::task::block_in_place(move || Handle::current().block_on(fut))
186 }
187
188 pub const fn canon_state_notification(
190 &self,
191 ) -> &broadcast::Sender<CanonStateNotification<PrimitivesTy<Node>>> {
192 &self.canon_state_notification
193 }
194}
195
196impl<P, Node, N> RpcBlockchainProvider<P, Node, N>
197where
198 P: Provider<N> + Clone + 'static,
199 N: Network,
200 Node: NodeTypes,
201{
202 fn create_state_provider(&self, block_id: BlockId) -> RpcBlockchainStateProvider<P, Node, N> {
204 RpcBlockchainStateProvider::with_chain_spec(
205 self.provider.clone(),
206 block_id,
207 self.chain_spec.clone(),
208 )
209 .with_compute_state_root(self.config.compute_state_root)
210 .with_reth_rpc_support(self.config.reth_rpc_support)
211 }
212
213 fn state_by_block_number(
215 &self,
216 block_number: BlockNumber,
217 ) -> Result<StateProviderBox, ProviderError> {
218 Ok(Box::new(self.create_state_provider(BlockId::number(block_number))))
219 }
220}
221
222impl<P, Node, N> BlockHashReader for RpcBlockchainProvider<P, Node, N>
228where
229 P: Provider<N> + Clone + 'static,
230 N: Network,
231 Node: NodeTypes,
232{
233 fn block_hash(&self, number: BlockNumber) -> Result<Option<B256>, ProviderError> {
234 let block = self.block_on_async(async {
235 self.provider.get_block_by_number(number.into()).await.map_err(ProviderError::other)
236 })?;
237 Ok(block.map(|b| b.header().hash()))
238 }
239
240 fn canonical_hashes_range(
241 &self,
242 _start: BlockNumber,
243 _end: BlockNumber,
244 ) -> Result<Vec<B256>, ProviderError> {
245 Err(ProviderError::UnsupportedProvider)
247 }
248}
249
250impl<P, Node, N> BlockNumReader for RpcBlockchainProvider<P, Node, N>
251where
252 P: Provider<N> + Clone + 'static,
253 N: Network,
254 Node: NodeTypes,
255{
256 fn chain_info(&self) -> Result<reth_chainspec::ChainInfo, ProviderError> {
257 self.block_on_async(async {
258 let block = self
259 .provider
260 .get_block(BlockId::Number(BlockNumberOrTag::Latest))
261 .await
262 .map_err(ProviderError::other)?
263 .ok_or(ProviderError::HeaderNotFound(0.into()))?;
264
265 Ok(ChainInfo { best_hash: block.header().hash(), best_number: block.header().number() })
266 })
267 }
268
269 fn best_block_number(&self) -> Result<BlockNumber, ProviderError> {
270 self.block_on_async(async {
271 self.provider.get_block_number().await.map_err(ProviderError::other)
272 })
273 }
274
275 fn last_block_number(&self) -> Result<BlockNumber, ProviderError> {
276 self.best_block_number()
277 }
278
279 fn block_number(&self, hash: B256) -> Result<Option<BlockNumber>, ProviderError> {
280 let block = self.block_on_async(async {
281 self.provider.get_block_by_hash(hash).await.map_err(ProviderError::other)
282 })?;
283 Ok(block.map(|b| b.header().number()))
284 }
285}
286
287impl<P, Node, N> BlockIdReader for RpcBlockchainProvider<P, Node, N>
288where
289 P: Provider<N> + Clone + 'static,
290 N: Network,
291 Node: NodeTypes,
292{
293 fn block_number_for_id(&self, block_id: BlockId) -> Result<Option<BlockNumber>, ProviderError> {
294 match block_id {
295 BlockId::Hash(hash) => {
296 let block = self.block_on_async(async {
297 self.provider
298 .get_block_by_hash(hash.block_hash)
299 .await
300 .map_err(ProviderError::other)
301 })?;
302 Ok(block.map(|b| b.header().number()))
303 }
304 BlockId::Number(number_or_tag) => match number_or_tag {
305 alloy_rpc_types::BlockNumberOrTag::Number(num) => Ok(Some(num)),
306 alloy_rpc_types::BlockNumberOrTag::Latest => self.block_on_async(async {
307 self.provider.get_block_number().await.map(Some).map_err(ProviderError::other)
308 }),
309 _ => Ok(None),
310 },
311 }
312 }
313
314 fn pending_block_num_hash(&self) -> Result<Option<alloy_eips::BlockNumHash>, ProviderError> {
315 Err(ProviderError::UnsupportedProvider)
317 }
318
319 fn safe_block_num_hash(&self) -> Result<Option<alloy_eips::BlockNumHash>, ProviderError> {
320 Err(ProviderError::UnsupportedProvider)
322 }
323
324 fn finalized_block_num_hash(&self) -> Result<Option<alloy_eips::BlockNumHash>, ProviderError> {
325 Err(ProviderError::UnsupportedProvider)
327 }
328}
329
330impl<P, Node, N> HeaderProvider for RpcBlockchainProvider<P, Node, N>
331where
332 P: Provider<N> + Clone + 'static,
333 N: Network,
334 Node: NodeTypes,
335 BlockTy<Node>: TryFromBlockResponse<N>,
336{
337 type Header = HeaderTy<Node>;
338
339 fn header(&self, block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
340 let block_response = self.block_on_async(async {
341 self.provider.get_block_by_hash(block_hash).await.map_err(ProviderError::other)
342 })?;
343
344 let Some(block_response) = block_response else {
345 return Ok(None);
347 };
348
349 let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
351 .map_err(ProviderError::other)?;
352
353 Ok(Some(block.into_header()))
354 }
355
356 fn header_by_number(&self, num: u64) -> ProviderResult<Option<Self::Header>> {
357 let Some(sealed_header) = self.sealed_header(num)? else {
358 return Ok(None);
360 };
361
362 Ok(Some(sealed_header.into_header()))
363 }
364
365 fn headers_range(
366 &self,
367 _range: impl RangeBounds<BlockNumber>,
368 ) -> ProviderResult<Vec<Self::Header>> {
369 Err(ProviderError::UnsupportedProvider)
370 }
371
372 fn sealed_header(
373 &self,
374 number: BlockNumber,
375 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
376 let block_response = self.block_on_async(async {
377 self.provider.get_block_by_number(number.into()).await.map_err(ProviderError::other)
378 })?;
379
380 let Some(block_response) = block_response else {
381 return Ok(None);
383 };
384 let block_hash = block_response.header().hash();
385
386 let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
388 .map_err(ProviderError::other)?;
389
390 Ok(Some(SealedHeader::new(block.into_header(), block_hash)))
391 }
392
393 fn sealed_headers_while(
394 &self,
395 _range: impl RangeBounds<BlockNumber>,
396 _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
397 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
398 Err(ProviderError::UnsupportedProvider)
399 }
400}
401
402impl<P, Node, N> BlockBodyIndicesProvider for RpcBlockchainProvider<P, Node, N>
403where
404 P: Provider<N> + Clone + 'static,
405 N: Network,
406 Node: NodeTypes,
407{
408 fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
409 Err(ProviderError::UnsupportedProvider)
410 }
411
412 fn block_body_indices_range(
413 &self,
414 _range: RangeInclusive<BlockNumber>,
415 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
416 Err(ProviderError::UnsupportedProvider)
417 }
418}
419
420impl<P, Node, N> BlockReader for RpcBlockchainProvider<P, Node, N>
421where
422 P: Provider<N> + Clone + 'static,
423 N: Network,
424 Node: NodeTypes,
425 BlockTy<Node>: TryFromBlockResponse<N>,
426 TxTy<Node>: TryFromTransactionResponse<N>,
427 ReceiptTy<Node>: TryFromReceiptResponse<N>,
428{
429 type Block = BlockTy<Node>;
430
431 fn find_block_by_hash(
432 &self,
433 _hash: B256,
434 _source: BlockSource,
435 ) -> ProviderResult<Option<Self::Block>> {
436 Err(ProviderError::UnsupportedProvider)
437 }
438
439 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
440 let block_response = self.block_on_async(async {
441 self.provider.get_block(id.into()).full().await.map_err(ProviderError::other)
442 })?;
443
444 let Some(block_response) = block_response else {
445 return Ok(None);
447 };
448
449 let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
451 .map_err(ProviderError::other)?;
452
453 Ok(Some(block))
454 }
455
456 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
457 Err(ProviderError::UnsupportedProvider)
458 }
459
460 fn pending_block_and_receipts(
461 &self,
462 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
463 Err(ProviderError::UnsupportedProvider)
464 }
465
466 fn recovered_block(
467 &self,
468 _id: BlockHashOrNumber,
469 _transaction_kind: TransactionVariant,
470 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
471 Err(ProviderError::UnsupportedProvider)
472 }
473
474 fn sealed_block_with_senders(
475 &self,
476 _id: BlockHashOrNumber,
477 _transaction_kind: TransactionVariant,
478 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
479 Err(ProviderError::UnsupportedProvider)
480 }
481
482 fn block_range(&self, _range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
483 Err(ProviderError::UnsupportedProvider)
484 }
485
486 fn block_with_senders_range(
487 &self,
488 _range: RangeInclusive<BlockNumber>,
489 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
490 Err(ProviderError::UnsupportedProvider)
491 }
492
493 fn recovered_block_range(
494 &self,
495 _range: RangeInclusive<BlockNumber>,
496 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
497 Err(ProviderError::UnsupportedProvider)
498 }
499
500 fn block_by_transaction_id(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
501 Err(ProviderError::UnsupportedProvider)
502 }
503}
504
505impl<P, Node, N> BlockReaderIdExt for RpcBlockchainProvider<P, Node, N>
506where
507 P: Provider<N> + Clone + 'static,
508 N: Network,
509 Node: NodeTypes,
510 BlockTy<Node>: TryFromBlockResponse<N>,
511 TxTy<Node>: TryFromTransactionResponse<N>,
512 ReceiptTy<Node>: TryFromReceiptResponse<N>,
513{
514 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
515 match id {
516 BlockId::Hash(hash) => self.block_by_hash(hash.block_hash),
517 BlockId::Number(number_or_tag) => self.block_by_number_or_tag(number_or_tag),
518 }
519 }
520
521 fn sealed_header_by_id(
522 &self,
523 id: BlockId,
524 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
525 match id {
526 BlockId::Hash(hash) => self.sealed_header_by_hash(hash.block_hash),
527 BlockId::Number(number_or_tag) => self.sealed_header_by_number_or_tag(number_or_tag),
528 }
529 }
530
531 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
532 match id {
533 BlockId::Hash(hash) => self.header_by_hash_or_number(hash.block_hash.into()),
534 BlockId::Number(number_or_tag) => self.header_by_number_or_tag(number_or_tag),
535 }
536 }
537}
538
539impl<P, Node, N> ReceiptProvider for RpcBlockchainProvider<P, Node, N>
540where
541 P: Provider<N> + Clone + 'static,
542 N: Network,
543 Node: NodeTypes,
544 ReceiptTy<Node>: TryFromReceiptResponse<N>,
545{
546 type Receipt = ReceiptTy<Node>;
547
548 fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
549 Err(ProviderError::UnsupportedProvider)
550 }
551
552 fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
553 let receipt_response = self.block_on_async(async {
554 self.provider.get_transaction_receipt(hash).await.map_err(ProviderError::other)
555 })?;
556
557 let Some(receipt_response) = receipt_response else {
558 return Ok(None);
560 };
561
562 let receipt =
564 <ReceiptTy<Node> as TryFromReceiptResponse<N>>::from_receipt_response(receipt_response)
565 .map_err(ProviderError::other)?;
566
567 Ok(Some(receipt))
568 }
569
570 fn receipts_by_block(
571 &self,
572 block: BlockHashOrNumber,
573 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
574 self.block_on_async(async {
575 let receipts_response = self
576 .provider
577 .get_block_receipts(block.into())
578 .await
579 .map_err(ProviderError::other)?;
580
581 let Some(receipts) = receipts_response else {
582 return Ok(None);
584 };
585
586 let receipts = receipts
588 .into_iter()
589 .map(|receipt_response| {
590 <ReceiptTy<Node> as TryFromReceiptResponse<N>>::from_receipt_response(
591 receipt_response,
592 )
593 .map_err(ProviderError::other)
594 })
595 .collect::<Result<Vec<_>, _>>()?;
596
597 Ok(Some(receipts))
598 })
599 }
600
601 fn receipts_by_tx_range(
602 &self,
603 _range: impl RangeBounds<TxNumber>,
604 ) -> ProviderResult<Vec<Self::Receipt>> {
605 Err(ProviderError::UnsupportedProvider)
606 }
607
608 fn receipts_by_block_range(
609 &self,
610 _block_range: RangeInclusive<BlockNumber>,
611 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
612 Err(ProviderError::UnsupportedProvider)
613 }
614}
615
616impl<P, Node, N> ReceiptProviderIdExt for RpcBlockchainProvider<P, Node, N>
617where
618 P: Provider<N> + Clone + 'static,
619 N: Network,
620 Node: NodeTypes,
621 ReceiptTy<Node>: TryFromReceiptResponse<N>,
622{
623}
624
625impl<P, Node, N> TransactionsProvider for RpcBlockchainProvider<P, Node, N>
626where
627 P: Provider<N> + Clone + 'static,
628 N: Network,
629 Node: NodeTypes,
630 BlockTy<Node>: TryFromBlockResponse<N>,
631 TxTy<Node>: TryFromTransactionResponse<N>,
632{
633 type Transaction = TxTy<Node>;
634
635 fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
636 Err(ProviderError::UnsupportedProvider)
637 }
638
639 fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
640 Err(ProviderError::UnsupportedProvider)
641 }
642
643 fn transaction_by_id_unhashed(
644 &self,
645 _id: TxNumber,
646 ) -> ProviderResult<Option<Self::Transaction>> {
647 Err(ProviderError::UnsupportedProvider)
648 }
649
650 fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
651 let transaction_response = self.block_on_async(async {
652 self.provider.get_transaction_by_hash(hash).await.map_err(ProviderError::other)
653 })?;
654
655 let Some(transaction_response) = transaction_response else {
656 return Ok(None);
658 };
659
660 let transaction = <TxTy<Node> as TryFromTransactionResponse<N>>::from_transaction_response(
662 transaction_response,
663 )
664 .map_err(ProviderError::other)?;
665
666 Ok(Some(transaction))
667 }
668
669 fn transaction_by_hash_with_meta(
670 &self,
671 _hash: TxHash,
672 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
673 Err(ProviderError::UnsupportedProvider)
674 }
675
676 fn transactions_by_block(
677 &self,
678 block: BlockHashOrNumber,
679 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
680 let block_response = self.block_on_async(async {
681 self.provider.get_block(block.into()).full().await.map_err(ProviderError::other)
682 })?;
683
684 let Some(block_response) = block_response else {
685 return Ok(None);
687 };
688
689 let block = <BlockTy<Node> as TryFromBlockResponse<N>>::from_block_response(block_response)
691 .map_err(ProviderError::other)?;
692
693 Ok(Some(block.into_body().into_transactions()))
694 }
695
696 fn transactions_by_block_range(
697 &self,
698 _range: impl RangeBounds<BlockNumber>,
699 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
700 Err(ProviderError::UnsupportedProvider)
701 }
702
703 fn transactions_by_tx_range(
704 &self,
705 _range: impl RangeBounds<TxNumber>,
706 ) -> ProviderResult<Vec<Self::Transaction>> {
707 Err(ProviderError::UnsupportedProvider)
708 }
709
710 fn senders_by_tx_range(
711 &self,
712 _range: impl RangeBounds<TxNumber>,
713 ) -> ProviderResult<Vec<Address>> {
714 Err(ProviderError::UnsupportedProvider)
715 }
716
717 fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
718 Err(ProviderError::UnsupportedProvider)
719 }
720}
721
722impl<P, Node, N> StateProviderFactory for RpcBlockchainProvider<P, Node, N>
723where
724 P: Provider<N> + Clone + 'static,
725 N: Network,
726 Node: NodeTypes,
727{
728 fn latest(&self) -> Result<StateProviderBox, ProviderError> {
729 Ok(Box::new(self.create_state_provider(self.best_block_number()?.into())))
730 }
731
732 fn state_by_block_id(&self, block_id: BlockId) -> Result<StateProviderBox, ProviderError> {
733 Ok(Box::new(self.create_state_provider(block_id)))
734 }
735
736 fn state_by_block_number_or_tag(
737 &self,
738 number_or_tag: alloy_rpc_types::BlockNumberOrTag,
739 ) -> Result<StateProviderBox, ProviderError> {
740 match number_or_tag {
741 alloy_rpc_types::BlockNumberOrTag::Latest => self.latest(),
742 alloy_rpc_types::BlockNumberOrTag::Pending => self.pending(),
743 alloy_rpc_types::BlockNumberOrTag::Number(num) => self.state_by_block_number(num),
744 _ => Err(ProviderError::UnsupportedProvider),
745 }
746 }
747
748 fn history_by_block_number(
749 &self,
750 block_number: BlockNumber,
751 ) -> Result<StateProviderBox, ProviderError> {
752 self.state_by_block_number(block_number)
753 }
754
755 fn history_by_block_hash(
756 &self,
757 block_hash: BlockHash,
758 ) -> Result<StateProviderBox, ProviderError> {
759 self.state_by_block_hash(block_hash)
760 }
761
762 fn state_by_block_hash(
763 &self,
764 block_hash: BlockHash,
765 ) -> Result<StateProviderBox, ProviderError> {
766 trace!(target: "alloy-provider", ?block_hash, "Getting state provider by block hash");
767
768 let block = self.block_on_async(async {
769 self.provider
770 .get_block_by_hash(block_hash)
771 .await
772 .map_err(ProviderError::other)?
773 .ok_or(ProviderError::BlockHashNotFound(block_hash))
774 })?;
775
776 let block_number = block.header().number();
777 Ok(Box::new(self.create_state_provider(BlockId::number(block_number))))
778 }
779
780 fn pending(&self) -> Result<StateProviderBox, ProviderError> {
781 trace!(target: "alloy-provider", "Getting pending state provider");
782 self.latest()
783 }
784
785 fn pending_state_by_hash(
786 &self,
787 _block_hash: B256,
788 ) -> Result<Option<StateProviderBox>, ProviderError> {
789 Err(ProviderError::UnsupportedProvider)
791 }
792
793 fn maybe_pending(&self) -> Result<Option<StateProviderBox>, ProviderError> {
794 Ok(None)
795 }
796}
797
798impl<P, Node, N> DatabaseProviderFactory for RpcBlockchainProvider<P, Node, N>
799where
800 P: Provider<N> + Clone + 'static,
801 N: Network,
802 Node: NodeTypes,
803{
804 type DB = DatabaseMock;
805 type Provider = RpcBlockchainStateProvider<P, Node, N>;
806 type ProviderRW = RpcBlockchainStateProvider<P, Node, N>;
807
808 fn database_provider_ro(&self) -> Result<Self::Provider, ProviderError> {
809 let block_number = self.block_on_async(async {
811 self.provider.get_block_number().await.map_err(ProviderError::other)
812 })?;
813
814 Ok(self.create_state_provider(BlockId::number(block_number)))
815 }
816
817 fn database_provider_rw(&self) -> Result<Self::ProviderRW, ProviderError> {
818 let block_number = self.block_on_async(async {
820 self.provider.get_block_number().await.map_err(ProviderError::other)
821 })?;
822
823 Ok(self.create_state_provider(BlockId::number(block_number)))
824 }
825}
826
827impl<P, Node, N> CanonChainTracker for RpcBlockchainProvider<P, Node, N>
828where
829 P: Provider<N> + Clone + 'static,
830 N: Network,
831 Node: NodeTypes,
832{
833 type Header = alloy_consensus::Header;
834 fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
835 }
837
838 fn last_received_update_timestamp(&self) -> Option<std::time::Instant> {
839 None
840 }
841
842 fn set_canonical_head(&self, _header: SealedHeader<Self::Header>) {
843 }
845
846 fn set_safe(&self, _header: SealedHeader<Self::Header>) {
847 }
849
850 fn set_finalized(&self, _header: SealedHeader<Self::Header>) {
851 }
853}
854
855impl<P, Node, N> NodePrimitivesProvider for RpcBlockchainProvider<P, Node, N>
856where
857 P: Send + Sync,
858 N: Send + Sync,
859 Node: NodeTypes,
860{
861 type Primitives = PrimitivesTy<Node>;
862}
863
864impl<P, Node, N> CanonStateSubscriptions for RpcBlockchainProvider<P, Node, N>
865where
866 P: Provider<N> + Clone + 'static,
867 N: Network,
868 Node: NodeTypes,
869{
870 fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<PrimitivesTy<Node>> {
871 trace!(target: "alloy-provider", "Subscribing to canonical state notifications");
872 self.canon_state_notification.subscribe()
873 }
874}
875
876impl<P, Node, N> ChainSpecProvider for RpcBlockchainProvider<P, Node, N>
877where
878 P: Send + Sync,
879 N: Send + Sync,
880 Node: NodeTypes,
881 Node::ChainSpec: Default,
882{
883 type ChainSpec = Node::ChainSpec;
884
885 fn chain_spec(&self) -> Arc<Self::ChainSpec> {
886 self.chain_spec.clone()
887 }
888}
889
890pub struct RpcBlockchainStateProvider<P, Node, N = alloy_network::AnyNetwork>
895where
896 Node: NodeTypes,
897{
898 provider: P,
900 block_id: BlockId,
902 node_types: std::marker::PhantomData<Node>,
904 network: std::marker::PhantomData<N>,
906 chain_spec: Option<Arc<Node::ChainSpec>>,
908 compute_state_root: bool,
910 code_store: DashMap<B256, Bytecode>,
914 reth_rpc_support: bool,
916}
917
918impl<P: std::fmt::Debug, Node: NodeTypes, N> std::fmt::Debug
919 for RpcBlockchainStateProvider<P, Node, N>
920{
921 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
922 f.debug_struct("RpcBlockchainStateProvider")
923 .field("provider", &self.provider)
924 .field("block_id", &self.block_id)
925 .finish()
926 }
927}
928
929impl<P: Clone, Node: NodeTypes, N> RpcBlockchainStateProvider<P, Node, N> {
930 pub fn new(
932 provider: P,
933 block_id: BlockId,
934 _primitives: std::marker::PhantomData<Node>,
935 ) -> Self {
936 Self {
937 provider,
938 block_id,
939 node_types: std::marker::PhantomData,
940 network: std::marker::PhantomData,
941 chain_spec: None,
942 compute_state_root: false,
943 code_store: Default::default(),
944 reth_rpc_support: true,
945 }
946 }
947
948 pub fn with_chain_spec(
950 provider: P,
951 block_id: BlockId,
952 chain_spec: Arc<Node::ChainSpec>,
953 ) -> Self {
954 Self {
955 provider,
956 block_id,
957 node_types: std::marker::PhantomData,
958 network: std::marker::PhantomData,
959 chain_spec: Some(chain_spec),
960 compute_state_root: false,
961 code_store: Default::default(),
962 reth_rpc_support: true,
963 }
964 }
965
966 fn block_on_async<F, T>(&self, fut: F) -> T
968 where
969 F: Future<Output = T>,
970 {
971 tokio::task::block_in_place(move || Handle::current().block_on(fut))
972 }
973
974 fn with_block_id(&self, block_id: BlockId) -> Self {
976 Self {
977 provider: self.provider.clone(),
978 block_id,
979 node_types: self.node_types,
980 network: self.network,
981 chain_spec: self.chain_spec.clone(),
982 compute_state_root: self.compute_state_root,
983 code_store: Default::default(),
984 reth_rpc_support: self.reth_rpc_support,
985 }
986 }
987
988 pub const fn with_compute_state_root(mut self, is_enable: bool) -> Self {
993 self.compute_state_root = is_enable;
994 self
995 }
996
997 pub const fn with_reth_rpc_support(mut self, is_enable: bool) -> Self {
1003 self.reth_rpc_support = is_enable;
1004 self
1005 }
1006
1007 fn get_account(&self, address: Address) -> Result<Option<Account>, ProviderError>
1009 where
1010 P: Provider<N> + Clone + 'static,
1011 N: Network,
1012 {
1013 let account_info = self.block_on_async(async {
1014 if self.reth_rpc_support {
1016 return self
1017 .provider
1018 .get_account_info(address)
1019 .block_id(self.block_id)
1020 .await
1021 .map_err(ProviderError::other);
1022 }
1023 let nonce = self.provider.get_transaction_count(address).block_id(self.block_id);
1025 let balance = self.provider.get_balance(address).block_id(self.block_id);
1026 let code = self.provider.get_code_at(address).block_id(self.block_id);
1027
1028 let (nonce, balance, code) = tokio::join!(nonce, balance, code,);
1029
1030 let account_info = AccountInfo {
1031 balance: balance.map_err(ProviderError::other)?,
1032 nonce: nonce.map_err(ProviderError::other)?,
1033 code: code.map_err(ProviderError::other)?,
1034 };
1035
1036 let code_hash = account_info.code_hash();
1037 if code_hash != KECCAK_EMPTY {
1038 self.code_store.insert(code_hash, Bytecode::new_raw(account_info.code.clone()));
1040 }
1041
1042 Ok(account_info)
1043 })?;
1044
1045 if account_info.balance.is_zero() && account_info.nonce == 0 && account_info.code.is_empty()
1047 {
1048 Ok(None)
1049 } else {
1050 let bytecode_hash =
1051 if account_info.code.is_empty() { None } else { Some(account_info.code_hash()) };
1052
1053 Ok(Some(Account {
1054 balance: account_info.balance,
1055 nonce: account_info.nonce,
1056 bytecode_hash,
1057 }))
1058 }
1059 }
1060}
1061
1062impl<P, Node, N> StateProvider for RpcBlockchainStateProvider<P, Node, N>
1063where
1064 P: Provider<N> + Clone + 'static,
1065 N: Network,
1066 Node: NodeTypes,
1067{
1068 fn storage(
1069 &self,
1070 address: Address,
1071 storage_key: StorageKey,
1072 ) -> Result<Option<U256>, ProviderError> {
1073 self.block_on_async(async {
1074 Ok(Some(
1075 self.provider
1076 .get_storage_at(address, storage_key.into())
1077 .block_id(self.block_id)
1078 .await
1079 .map_err(ProviderError::other)?,
1080 ))
1081 })
1082 }
1083
1084 fn storage_by_hashed_key(
1085 &self,
1086 _address: Address,
1087 _hashed_storage_key: StorageKey,
1088 ) -> Result<Option<U256>, ProviderError> {
1089 Err(ProviderError::UnsupportedProvider)
1090 }
1091
1092 fn account_code(&self, addr: &Address) -> Result<Option<Bytecode>, ProviderError> {
1093 self.block_on_async(async {
1094 let code = self
1095 .provider
1096 .get_code_at(*addr)
1097 .block_id(self.block_id)
1098 .await
1099 .map_err(ProviderError::other)?;
1100
1101 if code.is_empty() {
1102 Ok(None)
1103 } else {
1104 Ok(Some(Bytecode::new_raw(code)))
1105 }
1106 })
1107 }
1108
1109 fn account_balance(&self, addr: &Address) -> Result<Option<U256>, ProviderError> {
1110 self.get_account(*addr).map(|acc| acc.map(|a| a.balance))
1111 }
1112
1113 fn account_nonce(&self, addr: &Address) -> Result<Option<u64>, ProviderError> {
1114 self.get_account(*addr).map(|acc| acc.map(|a| a.nonce))
1115 }
1116}
1117
1118impl<P, Node, N> BytecodeReader for RpcBlockchainStateProvider<P, Node, N>
1119where
1120 P: Provider<N> + Clone + 'static,
1121 N: Network,
1122 Node: NodeTypes,
1123{
1124 fn bytecode_by_hash(&self, code_hash: &B256) -> Result<Option<Bytecode>, ProviderError> {
1125 if !self.reth_rpc_support {
1126 return Ok(self.code_store.get(code_hash).map(|entry| entry.value().clone()));
1127 }
1128
1129 self.block_on_async(async {
1130 let code = self
1132 .provider
1133 .debug_code_by_hash(*code_hash, None)
1134 .await
1135 .map_err(ProviderError::other)?;
1136
1137 let Some(code) = code else {
1138 return Ok(None);
1140 };
1141
1142 Ok(Some(Bytecode::new_raw(code)))
1143 })
1144 }
1145}
1146
1147impl<P, Node, N> AccountReader for RpcBlockchainStateProvider<P, Node, N>
1148where
1149 P: Provider<N> + Clone + 'static,
1150 N: Network,
1151 Node: NodeTypes,
1152{
1153 fn basic_account(&self, address: &Address) -> Result<Option<Account>, ProviderError> {
1154 self.get_account(*address)
1155 }
1156}
1157
1158impl<P, Node, N> StateRootProvider for RpcBlockchainStateProvider<P, Node, N>
1159where
1160 P: Provider<N> + Clone + 'static,
1161 N: Network,
1162 Node: NodeTypes,
1163{
1164 fn state_root(&self, hashed_state: HashedPostState) -> Result<B256, ProviderError> {
1165 self.state_root_from_nodes(TrieInput::from_state(hashed_state))
1166 }
1167
1168 fn state_root_from_nodes(&self, _input: TrieInput) -> Result<B256, ProviderError> {
1169 warn!("state_root_from_nodes is not implemented and will return zero");
1170 Ok(B256::ZERO)
1171 }
1172
1173 fn state_root_with_updates(
1174 &self,
1175 hashed_state: HashedPostState,
1176 ) -> Result<(B256, TrieUpdates), ProviderError> {
1177 if !self.compute_state_root {
1178 return Ok((B256::ZERO, TrieUpdates::default()));
1179 }
1180
1181 self.block_on_async(async {
1182 self.provider
1183 .raw_request::<(HashedPostState, BlockId), (B256, TrieUpdates)>(
1184 "debug_stateRootWithUpdates".into(),
1185 (hashed_state, self.block_id),
1186 )
1187 .into_future()
1188 .await
1189 .map_err(ProviderError::other)
1190 })
1191 }
1192
1193 fn state_root_from_nodes_with_updates(
1194 &self,
1195 _input: TrieInput,
1196 ) -> Result<(B256, TrieUpdates), ProviderError> {
1197 warn!("state_root_from_nodes_with_updates is not implemented and will return zero");
1198 Ok((B256::ZERO, TrieUpdates::default()))
1199 }
1200}
1201
1202impl<P, Node, N> StorageReader for RpcBlockchainStateProvider<P, Node, N>
1203where
1204 P: Provider<N> + Clone + 'static,
1205 N: Network,
1206 Node: NodeTypes,
1207{
1208 fn plain_state_storages(
1209 &self,
1210 addresses_with_keys: impl IntoIterator<Item = (Address, impl IntoIterator<Item = StorageKey>)>,
1211 ) -> Result<Vec<(Address, Vec<reth_primitives::StorageEntry>)>, ProviderError> {
1212 let mut results = Vec::new();
1213
1214 for (address, keys) in addresses_with_keys {
1215 let mut values = Vec::new();
1216 for key in keys {
1217 let value = self.storage(address, key)?.unwrap_or_default();
1218 values.push(reth_primitives::StorageEntry::new(key, value));
1219 }
1220 results.push((address, values));
1221 }
1222
1223 Ok(results)
1224 }
1225
1226 fn changed_storages_with_range(
1227 &self,
1228 _range: RangeInclusive<BlockNumber>,
1229 ) -> Result<BTreeMap<Address, std::collections::BTreeSet<StorageKey>>, ProviderError> {
1230 Ok(BTreeMap::new())
1231 }
1232
1233 fn changed_storages_and_blocks_with_range(
1234 &self,
1235 _range: RangeInclusive<BlockNumber>,
1236 ) -> Result<BTreeMap<(Address, StorageKey), Vec<u64>>, ProviderError> {
1237 Ok(BTreeMap::new())
1238 }
1239}
1240
1241impl<P, Node, N> reth_storage_api::StorageRootProvider for RpcBlockchainStateProvider<P, Node, N>
1242where
1243 P: Provider<N> + Clone + 'static,
1244 N: Network,
1245 Node: NodeTypes,
1246{
1247 fn storage_root(
1248 &self,
1249 _address: Address,
1250 _hashed_storage: reth_trie::HashedStorage,
1251 ) -> Result<B256, ProviderError> {
1252 Err(ProviderError::UnsupportedProvider)
1254 }
1255
1256 fn storage_proof(
1257 &self,
1258 _address: Address,
1259 _slot: B256,
1260 _hashed_storage: reth_trie::HashedStorage,
1261 ) -> Result<reth_trie::StorageProof, ProviderError> {
1262 Err(ProviderError::UnsupportedProvider)
1263 }
1264
1265 fn storage_multiproof(
1266 &self,
1267 _address: Address,
1268 _slots: &[B256],
1269 _hashed_storage: reth_trie::HashedStorage,
1270 ) -> Result<reth_trie::StorageMultiProof, ProviderError> {
1271 Err(ProviderError::UnsupportedProvider)
1272 }
1273}
1274
1275impl<P, Node, N> reth_storage_api::StateProofProvider for RpcBlockchainStateProvider<P, Node, N>
1276where
1277 P: Provider<N> + Clone + 'static,
1278 N: Network,
1279 Node: NodeTypes,
1280{
1281 fn proof(
1282 &self,
1283 _input: TrieInput,
1284 _address: Address,
1285 _slots: &[B256],
1286 ) -> Result<AccountProof, ProviderError> {
1287 Err(ProviderError::UnsupportedProvider)
1288 }
1289
1290 fn multiproof(
1291 &self,
1292 _input: TrieInput,
1293 _targets: reth_trie::MultiProofTargets,
1294 ) -> Result<MultiProof, ProviderError> {
1295 Err(ProviderError::UnsupportedProvider)
1296 }
1297
1298 fn witness(
1299 &self,
1300 _input: TrieInput,
1301 _target: HashedPostState,
1302 ) -> Result<Vec<alloy_primitives::Bytes>, ProviderError> {
1303 Err(ProviderError::UnsupportedProvider)
1304 }
1305}
1306
1307impl<P, Node, N> reth_storage_api::HashedPostStateProvider
1308 for RpcBlockchainStateProvider<P, Node, N>
1309where
1310 P: Provider<N> + Clone + 'static,
1311 N: Network,
1312 Node: NodeTypes,
1313{
1314 fn hashed_post_state(&self, _bundle_state: &revm::database::BundleState) -> HashedPostState {
1315 HashedPostState::default()
1317 }
1318}
1319
1320impl<P, Node, N> StateReader for RpcBlockchainStateProvider<P, Node, N>
1321where
1322 P: Provider<N> + Clone + 'static,
1323 N: Network,
1324 Node: NodeTypes,
1325{
1326 type Receipt = ReceiptTy<Node>;
1327
1328 fn get_state(
1329 &self,
1330 _block: BlockNumber,
1331 ) -> Result<Option<reth_execution_types::ExecutionOutcome<Self::Receipt>>, ProviderError> {
1332 Err(ProviderError::UnsupportedProvider)
1334 }
1335}
1336
1337impl<P, Node, N> DBProvider for RpcBlockchainStateProvider<P, Node, N>
1338where
1339 P: Provider<N> + Clone + 'static,
1340 N: Network,
1341 Node: NodeTypes,
1342{
1343 type Tx = TxMock;
1344
1345 fn tx_ref(&self) -> &Self::Tx {
1346 unimplemented!("tx_ref not supported for RPC provider")
1349 }
1350
1351 fn tx_mut(&mut self) -> &mut Self::Tx {
1352 unimplemented!("tx_mut not supported for RPC provider")
1353 }
1354
1355 fn into_tx(self) -> Self::Tx {
1356 TxMock::default()
1357 }
1358
1359 fn disable_long_read_transaction_safety(self) -> Self {
1360 self
1362 }
1363
1364 fn commit(self) -> ProviderResult<()> {
1365 unimplemented!("commit not supported for RPC provider")
1366 }
1367
1368 fn prune_modes_ref(&self) -> &reth_prune_types::PruneModes {
1369 unimplemented!("prune modes not supported for RPC provider")
1370 }
1371}
1372
1373impl<P, Node, N> BlockNumReader for RpcBlockchainStateProvider<P, Node, N>
1374where
1375 P: Provider<N> + Clone + 'static,
1376 N: Network,
1377 Node: NodeTypes,
1378{
1379 fn chain_info(&self) -> Result<ChainInfo, ProviderError> {
1380 self.block_on_async(async {
1381 let block = self
1382 .provider
1383 .get_block(self.block_id)
1384 .await
1385 .map_err(ProviderError::other)?
1386 .ok_or(ProviderError::HeaderNotFound(0.into()))?;
1387
1388 Ok(ChainInfo { best_hash: block.header().hash(), best_number: block.header().number() })
1389 })
1390 }
1391
1392 fn best_block_number(&self) -> Result<BlockNumber, ProviderError> {
1393 self.block_on_async(async {
1394 self.provider.get_block_number().await.map_err(ProviderError::other)
1395 })
1396 }
1397
1398 fn last_block_number(&self) -> Result<BlockNumber, ProviderError> {
1399 self.best_block_number()
1400 }
1401
1402 fn block_number(&self, hash: B256) -> Result<Option<BlockNumber>, ProviderError> {
1403 self.block_on_async(async {
1404 let block =
1405 self.provider.get_block_by_hash(hash).await.map_err(ProviderError::other)?;
1406
1407 Ok(block.map(|b| b.header().number()))
1408 })
1409 }
1410}
1411
1412impl<P, Node, N> BlockHashReader for RpcBlockchainStateProvider<P, Node, N>
1413where
1414 P: Provider<N> + Clone + 'static,
1415 N: Network,
1416 Node: NodeTypes,
1417{
1418 fn block_hash(&self, number: u64) -> Result<Option<B256>, ProviderError> {
1419 self.block_on_async(async {
1420 let block = self
1421 .provider
1422 .get_block_by_number(number.into())
1423 .await
1424 .map_err(ProviderError::other)?;
1425
1426 Ok(block.map(|b| b.header().hash()))
1427 })
1428 }
1429
1430 fn canonical_hashes_range(
1431 &self,
1432 _start: BlockNumber,
1433 _end: BlockNumber,
1434 ) -> Result<Vec<B256>, ProviderError> {
1435 Err(ProviderError::UnsupportedProvider)
1436 }
1437}
1438
1439impl<P, Node, N> BlockIdReader for RpcBlockchainStateProvider<P, Node, N>
1440where
1441 P: Provider<N> + Clone + 'static,
1442 N: Network,
1443 Node: NodeTypes,
1444{
1445 fn block_number_for_id(
1446 &self,
1447 _block_id: BlockId,
1448 ) -> Result<Option<BlockNumber>, ProviderError> {
1449 Err(ProviderError::UnsupportedProvider)
1450 }
1451
1452 fn pending_block_num_hash(&self) -> Result<Option<alloy_eips::BlockNumHash>, ProviderError> {
1453 Err(ProviderError::UnsupportedProvider)
1454 }
1455
1456 fn safe_block_num_hash(&self) -> Result<Option<alloy_eips::BlockNumHash>, ProviderError> {
1457 Err(ProviderError::UnsupportedProvider)
1458 }
1459
1460 fn finalized_block_num_hash(&self) -> Result<Option<alloy_eips::BlockNumHash>, ProviderError> {
1461 Err(ProviderError::UnsupportedProvider)
1462 }
1463}
1464
1465impl<P, Node, N> BlockReader for RpcBlockchainStateProvider<P, Node, N>
1466where
1467 P: Provider<N> + Clone + 'static,
1468 N: Network,
1469 Node: NodeTypes,
1470{
1471 type Block = BlockTy<Node>;
1472
1473 fn find_block_by_hash(
1474 &self,
1475 _hash: B256,
1476 _source: reth_provider::BlockSource,
1477 ) -> Result<Option<Self::Block>, ProviderError> {
1478 Err(ProviderError::UnsupportedProvider)
1479 }
1480
1481 fn block(
1482 &self,
1483 _id: alloy_rpc_types::BlockHashOrNumber,
1484 ) -> Result<Option<Self::Block>, ProviderError> {
1485 Err(ProviderError::UnsupportedProvider)
1486 }
1487
1488 fn pending_block(&self) -> Result<Option<RecoveredBlock<Self::Block>>, ProviderError> {
1489 Err(ProviderError::UnsupportedProvider)
1490 }
1491
1492 fn pending_block_and_receipts(
1493 &self,
1494 ) -> Result<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>, ProviderError> {
1495 Err(ProviderError::UnsupportedProvider)
1496 }
1497
1498 fn recovered_block(
1499 &self,
1500 _id: alloy_rpc_types::BlockHashOrNumber,
1501 _transaction_kind: TransactionVariant,
1502 ) -> Result<Option<RecoveredBlock<Self::Block>>, ProviderError> {
1503 Err(ProviderError::UnsupportedProvider)
1504 }
1505
1506 fn sealed_block_with_senders(
1507 &self,
1508 _id: alloy_rpc_types::BlockHashOrNumber,
1509 _transaction_kind: TransactionVariant,
1510 ) -> Result<Option<RecoveredBlock<BlockTy<Node>>>, ProviderError> {
1511 Err(ProviderError::UnsupportedProvider)
1512 }
1513
1514 fn block_range(
1515 &self,
1516 _range: RangeInclusive<BlockNumber>,
1517 ) -> Result<Vec<Self::Block>, ProviderError> {
1518 Err(ProviderError::UnsupportedProvider)
1519 }
1520
1521 fn block_with_senders_range(
1522 &self,
1523 _range: RangeInclusive<BlockNumber>,
1524 ) -> Result<Vec<RecoveredBlock<BlockTy<Node>>>, ProviderError> {
1525 Err(ProviderError::UnsupportedProvider)
1526 }
1527
1528 fn recovered_block_range(
1529 &self,
1530 _range: RangeInclusive<BlockNumber>,
1531 ) -> Result<Vec<RecoveredBlock<Self::Block>>, ProviderError> {
1532 Err(ProviderError::UnsupportedProvider)
1533 }
1534
1535 fn block_by_transaction_id(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
1536 Err(ProviderError::UnsupportedProvider)
1537 }
1538}
1539
1540impl<P, Node, N> TransactionsProvider for RpcBlockchainStateProvider<P, Node, N>
1541where
1542 P: Provider<N> + Clone + 'static,
1543 N: Network,
1544 Node: NodeTypes,
1545{
1546 type Transaction = TxTy<Node>;
1547
1548 fn transaction_id(&self, _tx_hash: B256) -> Result<Option<TxNumber>, ProviderError> {
1549 Err(ProviderError::UnsupportedProvider)
1550 }
1551
1552 fn transaction_by_id(&self, _id: TxNumber) -> Result<Option<Self::Transaction>, ProviderError> {
1553 Err(ProviderError::UnsupportedProvider)
1554 }
1555
1556 fn transaction_by_id_unhashed(
1557 &self,
1558 _id: TxNumber,
1559 ) -> Result<Option<Self::Transaction>, ProviderError> {
1560 Err(ProviderError::UnsupportedProvider)
1561 }
1562
1563 fn transaction_by_hash(&self, _hash: B256) -> Result<Option<Self::Transaction>, ProviderError> {
1564 Err(ProviderError::UnsupportedProvider)
1565 }
1566
1567 fn transaction_by_hash_with_meta(
1568 &self,
1569 _hash: B256,
1570 ) -> Result<Option<(Self::Transaction, TransactionMeta)>, ProviderError> {
1571 Err(ProviderError::UnsupportedProvider)
1572 }
1573
1574 fn transactions_by_block(
1575 &self,
1576 _block: alloy_rpc_types::BlockHashOrNumber,
1577 ) -> Result<Option<Vec<Self::Transaction>>, ProviderError> {
1578 Err(ProviderError::UnsupportedProvider)
1579 }
1580
1581 fn transactions_by_block_range(
1582 &self,
1583 _range: impl RangeBounds<BlockNumber>,
1584 ) -> Result<Vec<Vec<Self::Transaction>>, ProviderError> {
1585 Err(ProviderError::UnsupportedProvider)
1586 }
1587
1588 fn transactions_by_tx_range(
1589 &self,
1590 _range: impl RangeBounds<TxNumber>,
1591 ) -> Result<Vec<Self::Transaction>, ProviderError> {
1592 Err(ProviderError::UnsupportedProvider)
1593 }
1594
1595 fn senders_by_tx_range(
1596 &self,
1597 _range: impl RangeBounds<TxNumber>,
1598 ) -> Result<Vec<Address>, ProviderError> {
1599 Err(ProviderError::UnsupportedProvider)
1600 }
1601
1602 fn transaction_sender(&self, _id: TxNumber) -> Result<Option<Address>, ProviderError> {
1603 Err(ProviderError::UnsupportedProvider)
1604 }
1605}
1606
1607impl<P, Node, N> ReceiptProvider for RpcBlockchainStateProvider<P, Node, N>
1608where
1609 P: Provider<N> + Clone + 'static,
1610 N: Network,
1611 Node: NodeTypes,
1612{
1613 type Receipt = ReceiptTy<Node>;
1614
1615 fn receipt(&self, _id: TxNumber) -> Result<Option<Self::Receipt>, ProviderError> {
1616 Err(ProviderError::UnsupportedProvider)
1617 }
1618
1619 fn receipt_by_hash(&self, _hash: B256) -> Result<Option<Self::Receipt>, ProviderError> {
1620 Err(ProviderError::UnsupportedProvider)
1621 }
1622
1623 fn receipts_by_block(
1624 &self,
1625 _block: alloy_rpc_types::BlockHashOrNumber,
1626 ) -> Result<Option<Vec<Self::Receipt>>, ProviderError> {
1627 Err(ProviderError::UnsupportedProvider)
1628 }
1629
1630 fn receipts_by_tx_range(
1631 &self,
1632 _range: impl RangeBounds<TxNumber>,
1633 ) -> Result<Vec<Self::Receipt>, ProviderError> {
1634 Err(ProviderError::UnsupportedProvider)
1635 }
1636
1637 fn receipts_by_block_range(
1638 &self,
1639 _range: RangeInclusive<BlockNumber>,
1640 ) -> Result<Vec<Vec<Self::Receipt>>, ProviderError> {
1641 Err(ProviderError::UnsupportedProvider)
1642 }
1643}
1644
1645impl<P, Node, N> HeaderProvider for RpcBlockchainStateProvider<P, Node, N>
1646where
1647 P: Provider<N> + Clone + 'static,
1648 N: Network,
1649 Node: NodeTypes,
1650{
1651 type Header = HeaderTy<Node>;
1652
1653 fn header(&self, _block_hash: BlockHash) -> Result<Option<Self::Header>, ProviderError> {
1654 Err(ProviderError::UnsupportedProvider)
1655 }
1656
1657 fn header_by_number(&self, _num: BlockNumber) -> Result<Option<Self::Header>, ProviderError> {
1658 Err(ProviderError::UnsupportedProvider)
1659 }
1660
1661 fn headers_range(
1662 &self,
1663 _range: impl RangeBounds<BlockNumber>,
1664 ) -> Result<Vec<Self::Header>, ProviderError> {
1665 Err(ProviderError::UnsupportedProvider)
1666 }
1667
1668 fn sealed_header(
1669 &self,
1670 _number: BlockNumber,
1671 ) -> Result<Option<SealedHeader<HeaderTy<Node>>>, ProviderError> {
1672 Err(ProviderError::UnsupportedProvider)
1673 }
1674
1675 fn sealed_headers_range(
1676 &self,
1677 _range: impl RangeBounds<BlockNumber>,
1678 ) -> Result<Vec<SealedHeader<HeaderTy<Node>>>, ProviderError> {
1679 Err(ProviderError::UnsupportedProvider)
1680 }
1681
1682 fn sealed_headers_while(
1683 &self,
1684 _range: impl RangeBounds<BlockNumber>,
1685 _predicate: impl FnMut(&SealedHeader<HeaderTy<Node>>) -> bool,
1686 ) -> Result<Vec<SealedHeader<HeaderTy<Node>>>, ProviderError> {
1687 Err(ProviderError::UnsupportedProvider)
1688 }
1689}
1690
1691impl<P, Node, N> PruneCheckpointReader for RpcBlockchainStateProvider<P, Node, N>
1692where
1693 P: Provider<N> + Clone + 'static,
1694 N: Network,
1695 Node: NodeTypes,
1696{
1697 fn get_prune_checkpoint(
1698 &self,
1699 _segment: PruneSegment,
1700 ) -> Result<Option<PruneCheckpoint>, ProviderError> {
1701 Err(ProviderError::UnsupportedProvider)
1702 }
1703
1704 fn get_prune_checkpoints(&self) -> Result<Vec<(PruneSegment, PruneCheckpoint)>, ProviderError> {
1705 Err(ProviderError::UnsupportedProvider)
1706 }
1707}
1708
1709impl<P, Node, N> StageCheckpointReader for RpcBlockchainStateProvider<P, Node, N>
1710where
1711 P: Provider<N> + Clone + 'static,
1712 N: Network,
1713 Node: NodeTypes,
1714{
1715 fn get_stage_checkpoint(&self, _id: StageId) -> Result<Option<StageCheckpoint>, ProviderError> {
1716 Err(ProviderError::UnsupportedProvider)
1717 }
1718
1719 fn get_stage_checkpoint_progress(
1720 &self,
1721 _id: StageId,
1722 ) -> Result<Option<Vec<u8>>, ProviderError> {
1723 Err(ProviderError::UnsupportedProvider)
1724 }
1725
1726 fn get_all_checkpoints(&self) -> Result<Vec<(String, StageCheckpoint)>, ProviderError> {
1727 Err(ProviderError::UnsupportedProvider)
1728 }
1729}
1730
1731impl<P, Node, N> ChangeSetReader for RpcBlockchainStateProvider<P, Node, N>
1732where
1733 P: Provider<N> + Clone + 'static,
1734 N: Network,
1735 Node: NodeTypes,
1736{
1737 fn account_block_changeset(
1738 &self,
1739 _block_number: BlockNumber,
1740 ) -> Result<Vec<reth_db_api::models::AccountBeforeTx>, ProviderError> {
1741 Err(ProviderError::UnsupportedProvider)
1742 }
1743
1744 fn get_account_before_block(
1745 &self,
1746 _block_number: BlockNumber,
1747 _address: Address,
1748 ) -> ProviderResult<Option<reth_db_api::models::AccountBeforeTx>> {
1749 Err(ProviderError::UnsupportedProvider)
1750 }
1751
1752 fn account_changesets_range(
1753 &self,
1754 _range: impl std::ops::RangeBounds<BlockNumber>,
1755 ) -> ProviderResult<Vec<(BlockNumber, reth_db_api::models::AccountBeforeTx)>> {
1756 Err(ProviderError::UnsupportedProvider)
1757 }
1758
1759 fn account_changeset_count(&self) -> ProviderResult<usize> {
1760 Err(ProviderError::UnsupportedProvider)
1761 }
1762}
1763
1764impl<P, Node, N> StateProviderFactory for RpcBlockchainStateProvider<P, Node, N>
1765where
1766 P: Provider<N> + Clone + 'static + Send + Sync,
1767 Node: NodeTypes + 'static,
1768 Node::ChainSpec: Send + Sync,
1769 N: Network,
1770 Self: Clone + 'static,
1771{
1772 fn latest(&self) -> Result<StateProviderBox, ProviderError> {
1773 Ok(Box::new(self.with_block_id(self.best_block_number()?.into())))
1774 }
1775
1776 fn state_by_block_id(&self, block_id: BlockId) -> Result<StateProviderBox, ProviderError> {
1777 Ok(Box::new(self.with_block_id(block_id)))
1778 }
1779
1780 fn state_by_block_number_or_tag(
1781 &self,
1782 number_or_tag: alloy_rpc_types::BlockNumberOrTag,
1783 ) -> Result<StateProviderBox, ProviderError> {
1784 match number_or_tag {
1785 alloy_rpc_types::BlockNumberOrTag::Latest => self.latest(),
1786 alloy_rpc_types::BlockNumberOrTag::Pending => self.pending(),
1787 alloy_rpc_types::BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
1788 _ => Err(ProviderError::UnsupportedProvider),
1789 }
1790 }
1791
1792 fn history_by_block_number(
1793 &self,
1794 block_number: BlockNumber,
1795 ) -> Result<StateProviderBox, ProviderError> {
1796 Ok(Box::new(Self::new(
1797 self.provider.clone(),
1798 BlockId::number(block_number),
1799 self.node_types,
1800 )))
1801 }
1802
1803 fn history_by_block_hash(
1804 &self,
1805 block_hash: BlockHash,
1806 ) -> Result<StateProviderBox, ProviderError> {
1807 Ok(Box::new(self.with_block_id(BlockId::hash(block_hash))))
1808 }
1809
1810 fn state_by_block_hash(
1811 &self,
1812 block_hash: BlockHash,
1813 ) -> Result<StateProviderBox, ProviderError> {
1814 self.history_by_block_hash(block_hash)
1815 }
1816
1817 fn pending(&self) -> Result<StateProviderBox, ProviderError> {
1818 Ok(Box::new(self.clone()))
1819 }
1820
1821 fn pending_state_by_hash(
1822 &self,
1823 _block_hash: B256,
1824 ) -> Result<Option<StateProviderBox>, ProviderError> {
1825 Err(ProviderError::UnsupportedProvider)
1827 }
1828
1829 fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
1830 Ok(None)
1831 }
1832}
1833
1834impl<P, Node, N> ChainSpecProvider for RpcBlockchainStateProvider<P, Node, N>
1835where
1836 P: Send + Sync + std::fmt::Debug,
1837 N: Send + Sync,
1838 Node: NodeTypes,
1839 Node::ChainSpec: Default,
1840{
1841 type ChainSpec = Node::ChainSpec;
1842
1843 fn chain_spec(&self) -> Arc<Self::ChainSpec> {
1844 if let Some(chain_spec) = &self.chain_spec {
1845 chain_spec.clone()
1846 } else {
1847 Arc::new(Node::ChainSpec::default())
1849 }
1850 }
1851}
1852
1853impl<P, Node, N> StatsReader for RpcBlockchainStateProvider<P, Node, N>
1857where
1858 P: Provider<N> + Clone + 'static,
1859 N: Network,
1860 Node: NodeTypes,
1861{
1862 fn count_entries<T: reth_db_api::table::Table>(&self) -> Result<usize, ProviderError> {
1863 Ok(0)
1864 }
1865}
1866
1867impl<P, Node, N> BlockBodyIndicesProvider for RpcBlockchainStateProvider<P, Node, N>
1868where
1869 P: Provider<N> + Clone + 'static,
1870 N: Network,
1871 Node: NodeTypes,
1872{
1873 fn block_body_indices(
1874 &self,
1875 _num: u64,
1876 ) -> Result<Option<reth_db_api::models::StoredBlockBodyIndices>, ProviderError> {
1877 Err(ProviderError::UnsupportedProvider)
1878 }
1879
1880 fn block_body_indices_range(
1881 &self,
1882 _range: RangeInclusive<u64>,
1883 ) -> Result<Vec<reth_db_api::models::StoredBlockBodyIndices>, ProviderError> {
1884 Err(ProviderError::UnsupportedProvider)
1885 }
1886}
1887
1888impl<P, Node, N> NodePrimitivesProvider for RpcBlockchainStateProvider<P, Node, N>
1889where
1890 P: Send + Sync + std::fmt::Debug,
1891 N: Send + Sync,
1892 Node: NodeTypes,
1893{
1894 type Primitives = PrimitivesTy<Node>;
1895}
1896
1897impl<P, Node, N> ChainStateBlockReader for RpcBlockchainStateProvider<P, Node, N>
1898where
1899 P: Provider<N> + Clone + 'static,
1900 N: Network,
1901 Node: NodeTypes,
1902{
1903 fn last_finalized_block_number(&self) -> Result<Option<BlockNumber>, ProviderError> {
1904 Err(ProviderError::UnsupportedProvider)
1905 }
1906
1907 fn last_safe_block_number(&self) -> Result<Option<BlockNumber>, ProviderError> {
1908 Err(ProviderError::UnsupportedProvider)
1909 }
1910}
1911
1912impl<P, Node, N> ChainStateBlockWriter for RpcBlockchainStateProvider<P, Node, N>
1913where
1914 P: Provider<N> + Clone + 'static,
1915 N: Network,
1916 Node: NodeTypes,
1917{
1918 fn save_finalized_block_number(&self, _block_number: BlockNumber) -> Result<(), ProviderError> {
1919 Err(ProviderError::UnsupportedProvider)
1920 }
1921
1922 fn save_safe_block_number(&self, _block_number: BlockNumber) -> Result<(), ProviderError> {
1923 Err(ProviderError::UnsupportedProvider)
1924 }
1925}