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