reth_storage_api/
noop.rs

1//! Various noop implementations for traits.
2
3use crate::{
4    AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader,
5    BlockReader, BlockReaderIdExt, BlockSource, ChangeSetReader, HashedPostStateProvider,
6    HeaderProvider, NodePrimitivesProvider, OmmersProvider, PruneCheckpointReader, ReceiptProvider,
7    ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider, StateProvider,
8    StateProviderBox, StateProviderFactory, StateRootProvider, StorageRootProvider,
9    TransactionVariant, TransactionsProvider, WithdrawalsProvider,
10};
11use alloy_eips::{
12    eip4895::{Withdrawal, Withdrawals},
13    BlockHashOrNumber, BlockId, BlockNumberOrTag,
14};
15use alloy_primitives::{
16    map::{B256HashMap, HashMap},
17    Address, BlockHash, BlockNumber, Bytes, StorageKey, TxHash, TxNumber, B256, U256,
18};
19use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, MAINNET};
20use reth_db_models::{AccountBeforeTx, StoredBlockBodyIndices};
21use reth_primitives::{
22    BlockWithSenders, EthPrimitives, SealedBlockFor, SealedBlockWithSenders, TransactionMeta,
23};
24use reth_primitives_traits::{Account, Bytecode, NodePrimitives, SealedHeader};
25use reth_prune_types::{PruneCheckpoint, PruneSegment};
26use reth_stages_types::{StageCheckpoint, StageId};
27use reth_storage_errors::provider::{ProviderError, ProviderResult};
28use reth_trie::{
29    updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
30    MultiProofTargets, TrieInput,
31};
32use revm::primitives::FlaggedStorage;
33use std::{
34    marker::PhantomData,
35    ops::{RangeBounds, RangeInclusive},
36    sync::Arc,
37};
38
39/// Supports various api interfaces for testing purposes.
40#[derive(Debug)]
41#[non_exhaustive]
42pub struct NoopProvider<ChainSpec = reth_chainspec::ChainSpec, N = EthPrimitives> {
43    chain_spec: Arc<ChainSpec>,
44    _phantom: PhantomData<N>,
45}
46
47impl<ChainSpec, N> NoopProvider<ChainSpec, N> {
48    /// Create a new instance for specific primitive types.
49    pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
50        Self { chain_spec, _phantom: Default::default() }
51    }
52}
53
54impl<ChainSpec> NoopProvider<ChainSpec> {
55    /// Create a new instance of the `NoopBlockReader`.
56    pub fn eth(chain_spec: Arc<ChainSpec>) -> Self {
57        Self { chain_spec, _phantom: Default::default() }
58    }
59}
60
61impl NoopProvider {
62    /// Create a new instance of the [`NoopProvider`] with the mainnet chain spec.
63    pub fn mainnet() -> Self {
64        Self::eth(MAINNET.clone())
65    }
66}
67
68impl Default for NoopProvider {
69    fn default() -> Self {
70        Self::mainnet()
71    }
72}
73
74impl<ChainSpec, N> Clone for NoopProvider<ChainSpec, N> {
75    fn clone(&self) -> Self {
76        Self { chain_spec: Arc::clone(&self.chain_spec), _phantom: Default::default() }
77    }
78}
79
80/// Noop implementation for testing purposes
81impl<ChainSpec: Send + Sync, N: Send + Sync> BlockHashReader for NoopProvider<ChainSpec, N> {
82    fn block_hash(&self, _number: u64) -> ProviderResult<Option<B256>> {
83        Ok(None)
84    }
85
86    fn canonical_hashes_range(
87        &self,
88        _start: BlockNumber,
89        _end: BlockNumber,
90    ) -> ProviderResult<Vec<B256>> {
91        Ok(vec![])
92    }
93}
94
95impl<ChainSpec: Send + Sync, N: Send + Sync> BlockNumReader for NoopProvider<ChainSpec, N> {
96    fn chain_info(&self) -> ProviderResult<ChainInfo> {
97        Ok(ChainInfo::default())
98    }
99
100    fn best_block_number(&self) -> ProviderResult<BlockNumber> {
101        Ok(0)
102    }
103
104    fn last_block_number(&self) -> ProviderResult<BlockNumber> {
105        Ok(0)
106    }
107
108    fn block_number(&self, _hash: B256) -> ProviderResult<Option<BlockNumber>> {
109        Ok(None)
110    }
111}
112
113impl<ChainSpec: EthChainSpec + 'static, N: Send + Sync + 'static> ChainSpecProvider
114    for NoopProvider<ChainSpec, N>
115{
116    type ChainSpec = ChainSpec;
117
118    fn chain_spec(&self) -> Arc<Self::ChainSpec> {
119        self.chain_spec.clone()
120    }
121}
122
123impl<C: Send + Sync, N: NodePrimitives> BlockIdReader for NoopProvider<C, N> {
124    fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
125        Ok(None)
126    }
127
128    fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
129        Ok(None)
130    }
131
132    fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
133        Ok(None)
134    }
135}
136
137impl<C: Send + Sync, N: NodePrimitives> BlockReaderIdExt for NoopProvider<C, N> {
138    fn block_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::Block>> {
139        Ok(None)
140    }
141
142    fn sealed_header_by_id(
143        &self,
144        _id: BlockId,
145    ) -> ProviderResult<Option<SealedHeader<N::BlockHeader>>> {
146        Ok(None)
147    }
148
149    fn header_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::BlockHeader>> {
150        Ok(None)
151    }
152
153    fn ommers_by_id(&self, _id: BlockId) -> ProviderResult<Option<Vec<N::BlockHeader>>> {
154        Ok(None)
155    }
156}
157
158impl<C: Send + Sync, N: NodePrimitives> BlockReader for NoopProvider<C, N> {
159    type Block = N::Block;
160
161    fn find_block_by_hash(
162        &self,
163        _hash: B256,
164        _source: BlockSource,
165    ) -> ProviderResult<Option<Self::Block>> {
166        Ok(None)
167    }
168
169    fn block(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
170        Ok(None)
171    }
172
173    fn pending_block(&self) -> ProviderResult<Option<SealedBlockFor<Self::Block>>> {
174        Ok(None)
175    }
176
177    fn pending_block_with_senders(
178        &self,
179    ) -> ProviderResult<Option<SealedBlockWithSenders<Self::Block>>> {
180        Ok(None)
181    }
182
183    fn pending_block_and_receipts(
184        &self,
185    ) -> ProviderResult<Option<(SealedBlockFor<Self::Block>, Vec<Self::Receipt>)>> {
186        Ok(None)
187    }
188
189    fn block_with_senders(
190        &self,
191        _id: BlockHashOrNumber,
192        _transaction_kind: TransactionVariant,
193    ) -> ProviderResult<Option<BlockWithSenders<Self::Block>>> {
194        Ok(None)
195    }
196
197    fn sealed_block_with_senders(
198        &self,
199        _id: BlockHashOrNumber,
200        _transaction_kind: TransactionVariant,
201    ) -> ProviderResult<Option<SealedBlockWithSenders<Self::Block>>> {
202        Ok(None)
203    }
204
205    fn block_range(&self, _range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
206        Ok(vec![])
207    }
208
209    fn block_with_senders_range(
210        &self,
211        _range: RangeInclusive<BlockNumber>,
212    ) -> ProviderResult<Vec<BlockWithSenders<Self::Block>>> {
213        Ok(vec![])
214    }
215
216    fn sealed_block_with_senders_range(
217        &self,
218        _range: RangeInclusive<BlockNumber>,
219    ) -> ProviderResult<Vec<SealedBlockWithSenders<Self::Block>>> {
220        Ok(vec![])
221    }
222}
223
224impl<C: Send + Sync, N: NodePrimitives> TransactionsProvider for NoopProvider<C, N> {
225    type Transaction = N::SignedTx;
226
227    fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
228        Ok(None)
229    }
230
231    fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
232        Ok(None)
233    }
234
235    fn transaction_by_id_unhashed(
236        &self,
237        _id: TxNumber,
238    ) -> ProviderResult<Option<Self::Transaction>> {
239        Ok(None)
240    }
241
242    fn transaction_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
243        Ok(None)
244    }
245
246    fn transaction_by_hash_with_meta(
247        &self,
248        _hash: TxHash,
249    ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
250        Ok(None)
251    }
252
253    fn transaction_block(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
254        todo!()
255    }
256
257    fn transactions_by_block(
258        &self,
259        _block_id: BlockHashOrNumber,
260    ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
261        Ok(None)
262    }
263
264    fn transactions_by_block_range(
265        &self,
266        _range: impl RangeBounds<BlockNumber>,
267    ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
268        Ok(Vec::default())
269    }
270
271    fn transactions_by_tx_range(
272        &self,
273        _range: impl RangeBounds<TxNumber>,
274    ) -> ProviderResult<Vec<Self::Transaction>> {
275        Ok(Vec::default())
276    }
277
278    fn senders_by_tx_range(
279        &self,
280        _range: impl RangeBounds<TxNumber>,
281    ) -> ProviderResult<Vec<Address>> {
282        Ok(Vec::default())
283    }
284
285    fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
286        Ok(None)
287    }
288}
289
290impl<C: Send + Sync, N: NodePrimitives> ReceiptProvider for NoopProvider<C, N> {
291    type Receipt = N::Receipt;
292
293    fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
294        Ok(None)
295    }
296
297    fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
298        Ok(None)
299    }
300
301    fn receipts_by_block(
302        &self,
303        _block: BlockHashOrNumber,
304    ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
305        Ok(None)
306    }
307
308    fn receipts_by_tx_range(
309        &self,
310        _range: impl RangeBounds<TxNumber>,
311    ) -> ProviderResult<Vec<Self::Receipt>> {
312        Ok(vec![])
313    }
314}
315
316impl<C: Send + Sync, N: NodePrimitives> ReceiptProviderIdExt for NoopProvider<C, N> {}
317
318impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
319    type Header = N::BlockHeader;
320
321    fn header(&self, _block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
322        Ok(None)
323    }
324
325    fn header_by_number(&self, _num: u64) -> ProviderResult<Option<Self::Header>> {
326        Ok(None)
327    }
328
329    fn header_td(&self, _hash: &BlockHash) -> ProviderResult<Option<U256>> {
330        Ok(None)
331    }
332
333    fn header_td_by_number(&self, _number: BlockNumber) -> ProviderResult<Option<U256>> {
334        Ok(None)
335    }
336
337    fn headers_range(
338        &self,
339        _range: impl RangeBounds<BlockNumber>,
340    ) -> ProviderResult<Vec<Self::Header>> {
341        Ok(vec![])
342    }
343
344    fn sealed_header(
345        &self,
346        _number: BlockNumber,
347    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
348        Ok(None)
349    }
350
351    fn sealed_headers_while(
352        &self,
353        _range: impl RangeBounds<BlockNumber>,
354        _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
355    ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
356        Ok(vec![])
357    }
358}
359
360impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
361    fn basic_account(&self, _address: Address) -> ProviderResult<Option<Account>> {
362        Ok(None)
363    }
364}
365
366impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
367    fn account_block_changeset(
368        &self,
369        _block_number: BlockNumber,
370    ) -> ProviderResult<Vec<AccountBeforeTx>> {
371        Ok(Vec::default())
372    }
373}
374
375impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
376    fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
377        Ok(B256::default())
378    }
379
380    fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
381        Ok(B256::default())
382    }
383
384    fn state_root_with_updates(
385        &self,
386        _state: HashedPostState,
387    ) -> ProviderResult<(B256, TrieUpdates)> {
388        Ok((B256::default(), TrieUpdates::default()))
389    }
390
391    fn state_root_from_nodes_with_updates(
392        &self,
393        _input: TrieInput,
394    ) -> ProviderResult<(B256, TrieUpdates)> {
395        Ok((B256::default(), TrieUpdates::default()))
396    }
397}
398
399impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
400    fn storage_root(
401        &self,
402        _address: Address,
403        _hashed_storage: HashedStorage,
404    ) -> ProviderResult<B256> {
405        Ok(B256::default())
406    }
407
408    fn storage_proof(
409        &self,
410        _address: Address,
411        slot: B256,
412        _hashed_storage: HashedStorage,
413    ) -> ProviderResult<reth_trie::StorageProof> {
414        Ok(reth_trie::StorageProof::new(slot))
415    }
416
417    fn storage_multiproof(
418        &self,
419        _address: Address,
420        _slots: &[B256],
421        _hashed_storage: HashedStorage,
422    ) -> ProviderResult<reth_trie::StorageMultiProof> {
423        Ok(reth_trie::StorageMultiProof::empty())
424    }
425}
426
427impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
428    fn proof(
429        &self,
430        _input: TrieInput,
431        address: Address,
432        _slots: &[B256],
433    ) -> ProviderResult<AccountProof> {
434        Ok(AccountProof::new(address))
435    }
436
437    fn multiproof(
438        &self,
439        _input: TrieInput,
440        _targets: MultiProofTargets,
441    ) -> ProviderResult<MultiProof> {
442        Ok(MultiProof::default())
443    }
444
445    fn witness(
446        &self,
447        _input: TrieInput,
448        _target: HashedPostState,
449    ) -> ProviderResult<B256HashMap<Bytes>> {
450        Ok(HashMap::default())
451    }
452}
453
454impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
455    fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState {
456        HashedPostState::default()
457    }
458}
459
460impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
461    fn storage(
462        &self,
463        _account: Address,
464        _storage_key: StorageKey,
465    ) -> ProviderResult<Option<FlaggedStorage>> {
466        Ok(None)
467    }
468
469    fn bytecode_by_hash(&self, _code_hash: B256) -> ProviderResult<Option<Bytecode>> {
470        Ok(None)
471    }
472}
473
474impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
475    fn latest(&self) -> ProviderResult<StateProviderBox> {
476        Ok(Box::new(self.clone()))
477    }
478
479    fn state_by_block_number_or_tag(
480        &self,
481        number_or_tag: BlockNumberOrTag,
482    ) -> ProviderResult<StateProviderBox> {
483        match number_or_tag {
484            BlockNumberOrTag::Latest => self.latest(),
485            BlockNumberOrTag::Finalized => {
486                // we can only get the finalized state by hash, not by num
487                let hash =
488                    self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
489
490                // only look at historical state
491                self.history_by_block_hash(hash)
492            }
493            BlockNumberOrTag::Safe => {
494                // we can only get the safe state by hash, not by num
495                let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
496
497                self.history_by_block_hash(hash)
498            }
499            BlockNumberOrTag::Earliest => self.history_by_block_number(0),
500            BlockNumberOrTag::Pending => self.pending(),
501            BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
502        }
503    }
504
505    fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
506        Ok(Box::new(self.clone()))
507    }
508
509    fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
510        Ok(Box::new(self.clone()))
511    }
512
513    fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
514        Ok(Box::new(self.clone()))
515    }
516
517    fn pending(&self) -> ProviderResult<StateProviderBox> {
518        Ok(Box::new(self.clone()))
519    }
520
521    fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
522        Ok(Some(Box::new(self.clone())))
523    }
524}
525
526impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
527    fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
528        Ok(None)
529    }
530
531    fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
532        Ok(None)
533    }
534
535    fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
536        Ok(Vec::new())
537    }
538}
539
540impl<C: Send + Sync, N: NodePrimitives> WithdrawalsProvider for NoopProvider<C, N> {
541    fn withdrawals_by_block(
542        &self,
543        _id: BlockHashOrNumber,
544        _timestamp: u64,
545    ) -> ProviderResult<Option<Withdrawals>> {
546        Ok(None)
547    }
548    fn latest_withdrawal(&self) -> ProviderResult<Option<Withdrawal>> {
549        Ok(None)
550    }
551}
552
553impl<C: Send + Sync, N: NodePrimitives> OmmersProvider for NoopProvider<C, N> {
554    fn ommers(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
555        Ok(None)
556    }
557}
558
559impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
560    fn get_prune_checkpoint(
561        &self,
562        _segment: PruneSegment,
563    ) -> ProviderResult<Option<PruneCheckpoint>> {
564        Ok(None)
565    }
566
567    fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
568        Ok(Vec::new())
569    }
570}
571
572impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
573    type Primitives = N;
574}
575
576impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
577    fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
578        Ok(None)
579    }
580}