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