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