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