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