1use crate::{
4 AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader,
5 BlockReader, BlockReaderIdExt, BlockSource, BytecodeReader, ChangeSetReader,
6 HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider, PruneCheckpointReader,
7 ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider,
8 StateProvider, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider,
9 StorageRootProvider, TransactionVariant, TransactionsProvider,
10};
11
12#[cfg(feature = "db-api")]
13use crate::{DBProvider, DatabaseProviderFactory, StorageChangeSetReader};
14use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
15use alloy_consensus::transaction::TransactionMeta;
16use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
17use alloy_primitives::{
18 Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256,
19};
20use core::{
21 fmt::Debug,
22 marker::PhantomData,
23 ops::{RangeBounds, RangeInclusive},
24};
25use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, MAINNET};
26#[cfg(feature = "db-api")]
27use reth_db_api::mock::{DatabaseMock, TxMock};
28use reth_db_models::{AccountBeforeTx, StoredBlockBodyIndices};
29use reth_ethereum_primitives::EthPrimitives;
30use reth_execution_types::ExecutionOutcome;
31use reth_primitives_traits::{
32 Account, Bytecode, NodePrimitives, RecoveredBlock, SealedHeader, StorageEntry,
33};
34#[cfg(feature = "db-api")]
35use reth_prune_types::PruneModes;
36use reth_prune_types::{PruneCheckpoint, PruneSegment};
37use reth_stages_types::{StageCheckpoint, StageId};
38use reth_storage_errors::provider::{ProviderError, ProviderResult};
39use reth_trie_common::{
40 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
41 MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
42};
43
44#[derive(Debug)]
46#[non_exhaustive]
47pub struct NoopProvider<ChainSpec = reth_chainspec::ChainSpec, N = EthPrimitives> {
48 chain_spec: Arc<ChainSpec>,
49 #[cfg(feature = "db-api")]
50 tx: TxMock,
51 #[cfg(feature = "db-api")]
52 prune_modes: PruneModes,
53 _phantom: PhantomData<N>,
54}
55
56impl<ChainSpec, N> NoopProvider<ChainSpec, N> {
57 pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
59 Self {
60 chain_spec,
61 #[cfg(feature = "db-api")]
62 tx: TxMock::default(),
63 #[cfg(feature = "db-api")]
64 prune_modes: PruneModes::default(),
65 _phantom: Default::default(),
66 }
67 }
68}
69
70impl<ChainSpec> NoopProvider<ChainSpec> {
71 pub fn eth(chain_spec: Arc<ChainSpec>) -> Self {
73 Self {
74 chain_spec,
75 #[cfg(feature = "db-api")]
76 tx: TxMock::default(),
77 #[cfg(feature = "db-api")]
78 prune_modes: PruneModes::default(),
79 _phantom: Default::default(),
80 }
81 }
82}
83
84impl NoopProvider {
85 pub fn mainnet() -> Self {
87 Self::eth(MAINNET.clone())
88 }
89}
90
91impl Default for NoopProvider {
92 fn default() -> Self {
93 Self::mainnet()
94 }
95}
96
97impl<ChainSpec, N> Clone for NoopProvider<ChainSpec, N> {
98 fn clone(&self) -> Self {
99 Self {
100 chain_spec: Arc::clone(&self.chain_spec),
101 #[cfg(feature = "db-api")]
102 tx: self.tx.clone(),
103 #[cfg(feature = "db-api")]
104 prune_modes: self.prune_modes.clone(),
105 _phantom: Default::default(),
106 }
107 }
108}
109
110impl<ChainSpec: Send + Sync, N: Send + Sync> BlockHashReader for NoopProvider<ChainSpec, N> {
112 fn block_hash(&self, _number: u64) -> ProviderResult<Option<B256>> {
113 Ok(None)
114 }
115
116 fn canonical_hashes_range(
117 &self,
118 _start: BlockNumber,
119 _end: BlockNumber,
120 ) -> ProviderResult<Vec<B256>> {
121 Ok(Vec::new())
122 }
123}
124
125impl<ChainSpec: Send + Sync, N: Send + Sync> BlockNumReader for NoopProvider<ChainSpec, N> {
126 fn chain_info(&self) -> ProviderResult<ChainInfo> {
127 Ok(ChainInfo::default())
128 }
129
130 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
131 Ok(0)
132 }
133
134 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
135 Ok(0)
136 }
137
138 fn block_number(&self, _hash: B256) -> ProviderResult<Option<BlockNumber>> {
139 Ok(None)
140 }
141}
142
143impl<ChainSpec: EthChainSpec + 'static, N: Debug + Send + Sync + 'static> ChainSpecProvider
144 for NoopProvider<ChainSpec, N>
145{
146 type ChainSpec = ChainSpec;
147
148 fn chain_spec(&self) -> Arc<Self::ChainSpec> {
149 self.chain_spec.clone()
150 }
151}
152
153impl<C: Send + Sync, N: NodePrimitives> BlockIdReader for NoopProvider<C, N> {
154 fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
155 Ok(None)
156 }
157
158 fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
159 Ok(None)
160 }
161
162 fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
163 Ok(None)
164 }
165}
166
167impl<C: Send + Sync, N: NodePrimitives> BlockReaderIdExt for NoopProvider<C, N> {
168 fn block_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::Block>> {
169 Ok(None)
170 }
171
172 fn sealed_header_by_id(
173 &self,
174 _id: BlockId,
175 ) -> ProviderResult<Option<SealedHeader<N::BlockHeader>>> {
176 Ok(None)
177 }
178
179 fn header_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::BlockHeader>> {
180 Ok(None)
181 }
182}
183
184impl<C: Send + Sync, N: NodePrimitives> BlockReader for NoopProvider<C, N> {
185 type Block = N::Block;
186
187 fn find_block_by_hash(
188 &self,
189 _hash: B256,
190 _source: BlockSource,
191 ) -> ProviderResult<Option<Self::Block>> {
192 Ok(None)
193 }
194
195 fn block(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
196 Ok(None)
197 }
198
199 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
200 Ok(None)
201 }
202
203 fn pending_block_and_receipts(
204 &self,
205 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
206 Ok(None)
207 }
208
209 fn recovered_block(
210 &self,
211 _id: BlockHashOrNumber,
212 _transaction_kind: TransactionVariant,
213 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
214 Ok(None)
215 }
216
217 fn sealed_block_with_senders(
218 &self,
219 _id: BlockHashOrNumber,
220 _transaction_kind: TransactionVariant,
221 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
222 Ok(None)
223 }
224
225 fn block_range(&self, _range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
226 Ok(Vec::new())
227 }
228
229 fn block_with_senders_range(
230 &self,
231 _range: RangeInclusive<BlockNumber>,
232 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
233 Ok(Vec::new())
234 }
235
236 fn recovered_block_range(
237 &self,
238 _range: RangeInclusive<BlockNumber>,
239 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
240 Ok(Vec::new())
241 }
242
243 fn block_by_transaction_id(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
244 Ok(None)
245 }
246}
247
248impl<C: Send + Sync, N: NodePrimitives> TransactionsProvider for NoopProvider<C, N> {
249 type Transaction = N::SignedTx;
250
251 fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
252 Ok(None)
253 }
254
255 fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
256 Ok(None)
257 }
258
259 fn transaction_by_id_unhashed(
260 &self,
261 _id: TxNumber,
262 ) -> ProviderResult<Option<Self::Transaction>> {
263 Ok(None)
264 }
265
266 fn transaction_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
267 Ok(None)
268 }
269
270 fn transaction_by_hash_with_meta(
271 &self,
272 _hash: TxHash,
273 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
274 Ok(None)
275 }
276
277 fn transactions_by_block(
278 &self,
279 _block_id: BlockHashOrNumber,
280 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
281 Ok(None)
282 }
283
284 fn transactions_by_block_range(
285 &self,
286 _range: impl RangeBounds<BlockNumber>,
287 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
288 Ok(Vec::default())
289 }
290
291 fn transactions_by_tx_range(
292 &self,
293 _range: impl RangeBounds<TxNumber>,
294 ) -> ProviderResult<Vec<Self::Transaction>> {
295 Ok(Vec::default())
296 }
297
298 fn senders_by_tx_range(
299 &self,
300 _range: impl RangeBounds<TxNumber>,
301 ) -> ProviderResult<Vec<Address>> {
302 Ok(Vec::default())
303 }
304
305 fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
306 Ok(None)
307 }
308}
309
310impl<C: Send + Sync, N: NodePrimitives> ReceiptProvider for NoopProvider<C, N> {
311 type Receipt = N::Receipt;
312
313 fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
314 Ok(None)
315 }
316
317 fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
318 Ok(None)
319 }
320
321 fn receipts_by_block(
322 &self,
323 _block: BlockHashOrNumber,
324 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
325 Ok(None)
326 }
327
328 fn receipts_by_tx_range(
329 &self,
330 _range: impl RangeBounds<TxNumber>,
331 ) -> ProviderResult<Vec<Self::Receipt>> {
332 Ok(Vec::new())
333 }
334
335 fn receipts_by_block_range(
336 &self,
337 _block_range: RangeInclusive<BlockNumber>,
338 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
339 Ok(Vec::new())
340 }
341}
342
343impl<C: Send + Sync, N: NodePrimitives> ReceiptProviderIdExt for NoopProvider<C, N> {}
344
345impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
346 type Header = N::BlockHeader;
347
348 fn header(&self, _block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
349 Ok(None)
350 }
351
352 fn header_by_number(&self, _num: u64) -> ProviderResult<Option<Self::Header>> {
353 Ok(None)
354 }
355
356 fn headers_range(
357 &self,
358 _range: impl RangeBounds<BlockNumber>,
359 ) -> ProviderResult<Vec<Self::Header>> {
360 Ok(Vec::new())
361 }
362
363 fn sealed_header(
364 &self,
365 _number: BlockNumber,
366 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
367 Ok(None)
368 }
369
370 fn sealed_headers_while(
371 &self,
372 _range: impl RangeBounds<BlockNumber>,
373 _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
374 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
375 Ok(Vec::new())
376 }
377}
378
379impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
380 fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
381 Ok(None)
382 }
383}
384
385impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
386 fn account_block_changeset(
387 &self,
388 _block_number: BlockNumber,
389 ) -> ProviderResult<Vec<AccountBeforeTx>> {
390 Ok(Vec::default())
391 }
392
393 fn get_account_before_block(
394 &self,
395 _block_number: BlockNumber,
396 _address: Address,
397 ) -> ProviderResult<Option<AccountBeforeTx>> {
398 Ok(None)
399 }
400
401 fn account_changesets_range(
402 &self,
403 _range: impl core::ops::RangeBounds<BlockNumber>,
404 ) -> ProviderResult<Vec<(BlockNumber, AccountBeforeTx)>> {
405 Ok(Vec::default())
406 }
407
408 fn account_changeset_count(&self) -> ProviderResult<usize> {
409 Ok(0)
410 }
411}
412
413#[cfg(feature = "db-api")]
414impl<C: Send + Sync, N: NodePrimitives> StorageChangeSetReader for NoopProvider<C, N> {
415 fn storage_changeset(
416 &self,
417 _block_number: BlockNumber,
418 ) -> ProviderResult<Vec<(reth_db_api::models::BlockNumberAddress, StorageEntry)>> {
419 Ok(Vec::default())
420 }
421
422 fn get_storage_before_block(
423 &self,
424 _block_number: BlockNumber,
425 _address: Address,
426 _storage_key: B256,
427 ) -> ProviderResult<Option<StorageEntry>> {
428 Ok(None)
429 }
430
431 fn storage_changesets_range(
432 &self,
433 _range: RangeInclusive<BlockNumber>,
434 ) -> ProviderResult<Vec<(reth_db_api::models::BlockNumberAddress, StorageEntry)>> {
435 Ok(Vec::default())
436 }
437
438 fn storage_changeset_count(&self) -> ProviderResult<usize> {
439 Ok(0)
440 }
441}
442
443impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
444 fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
445 Ok(B256::default())
446 }
447
448 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
449 Ok(B256::default())
450 }
451
452 fn state_root_with_updates(
453 &self,
454 _state: HashedPostState,
455 ) -> ProviderResult<(B256, TrieUpdates)> {
456 Ok((B256::default(), TrieUpdates::default()))
457 }
458
459 fn state_root_from_nodes_with_updates(
460 &self,
461 _input: TrieInput,
462 ) -> ProviderResult<(B256, TrieUpdates)> {
463 Ok((B256::default(), TrieUpdates::default()))
464 }
465}
466
467impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
468 fn storage_root(
469 &self,
470 _address: Address,
471 _hashed_storage: HashedStorage,
472 ) -> ProviderResult<B256> {
473 Ok(B256::default())
474 }
475
476 fn storage_proof(
477 &self,
478 _address: Address,
479 slot: B256,
480 _hashed_storage: HashedStorage,
481 ) -> ProviderResult<StorageProof> {
482 Ok(StorageProof::new(slot))
483 }
484
485 fn storage_multiproof(
486 &self,
487 _address: Address,
488 _slots: &[B256],
489 _hashed_storage: HashedStorage,
490 ) -> ProviderResult<StorageMultiProof> {
491 Ok(StorageMultiProof::empty())
492 }
493}
494
495impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
496 fn proof(
497 &self,
498 _input: TrieInput,
499 address: Address,
500 _slots: &[B256],
501 ) -> ProviderResult<AccountProof> {
502 Ok(AccountProof::new(address))
503 }
504
505 fn multiproof(
506 &self,
507 _input: TrieInput,
508 _targets: MultiProofTargets,
509 ) -> ProviderResult<MultiProof> {
510 Ok(MultiProof::default())
511 }
512
513 fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
514 Ok(Vec::default())
515 }
516}
517
518impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
519 fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
520 HashedPostState::default()
521 }
522}
523
524impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
525 type Receipt = N::Receipt;
526
527 fn get_state(
528 &self,
529 _block: BlockNumber,
530 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
531 Ok(None)
532 }
533}
534
535impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
536 fn storage(
537 &self,
538 _account: Address,
539 _storage_key: StorageKey,
540 ) -> ProviderResult<Option<StorageValue>> {
541 Ok(None)
542 }
543}
544
545impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
546 fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
547 Ok(None)
548 }
549}
550
551impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
552 fn latest(&self) -> ProviderResult<StateProviderBox> {
553 Ok(Box::new(self.clone()))
554 }
555
556 fn state_by_block_number_or_tag(
557 &self,
558 number_or_tag: BlockNumberOrTag,
559 ) -> ProviderResult<StateProviderBox> {
560 match number_or_tag {
561 BlockNumberOrTag::Latest => self.latest(),
562 BlockNumberOrTag::Finalized => {
563 let hash =
565 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
566
567 self.history_by_block_hash(hash)
569 }
570 BlockNumberOrTag::Safe => {
571 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
573
574 self.history_by_block_hash(hash)
575 }
576 BlockNumberOrTag::Earliest => {
577 self.history_by_block_number(self.earliest_block_number()?)
578 }
579 BlockNumberOrTag::Pending => self.pending(),
580 BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
581 }
582 }
583
584 fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
585 Ok(Box::new(self.clone()))
586 }
587
588 fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
589 Ok(Box::new(self.clone()))
590 }
591
592 fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
593 Ok(Box::new(self.clone()))
594 }
595
596 fn pending(&self) -> ProviderResult<StateProviderBox> {
597 Ok(Box::new(self.clone()))
598 }
599
600 fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
601 Ok(Some(Box::new(self.clone())))
602 }
603
604 fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
605 Ok(Some(Box::new(self.clone())))
606 }
607}
608
609impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
610 fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
611 Ok(None)
612 }
613
614 fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
615 Ok(None)
616 }
617
618 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
619 Ok(Vec::new())
620 }
621}
622
623impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
624 fn get_prune_checkpoint(
625 &self,
626 _segment: PruneSegment,
627 ) -> ProviderResult<Option<PruneCheckpoint>> {
628 Ok(None)
629 }
630
631 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
632 Ok(Vec::new())
633 }
634}
635
636impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
637 type Primitives = N;
638}
639
640impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
641 fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
642 Ok(None)
643 }
644
645 fn block_body_indices_range(
646 &self,
647 _range: RangeInclusive<BlockNumber>,
648 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
649 Ok(Vec::new())
650 }
651}
652
653#[cfg(feature = "db-api")]
654impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
655 type Tx = TxMock;
656
657 fn tx_ref(&self) -> &Self::Tx {
658 &self.tx
659 }
660
661 fn tx_mut(&mut self) -> &mut Self::Tx {
662 &mut self.tx
663 }
664
665 fn into_tx(self) -> Self::Tx {
666 self.tx
667 }
668
669 fn prune_modes_ref(&self) -> &PruneModes {
670 &self.prune_modes
671 }
672
673 fn commit(self) -> ProviderResult<()> {
674 use reth_db_api::transaction::DbTx;
675
676 Ok(self.tx.commit()?)
677 }
678}
679
680#[cfg(feature = "db-api")]
681impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
682 for NoopProvider<ChainSpec, N>
683{
684 type DB = DatabaseMock;
685 type Provider = Self;
686 type ProviderRW = Self;
687
688 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
689 Ok(self.clone())
690 }
691
692 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
693 Ok(self.clone())
694 }
695}