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 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#[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 pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
50 Self { chain_spec, _phantom: Default::default() }
51 }
52}
53
54impl<ChainSpec> NoopProvider<ChainSpec> {
55 pub fn eth(chain_spec: Arc<ChainSpec>) -> Self {
57 Self { chain_spec, _phantom: Default::default() }
58 }
59}
60
61impl NoopProvider {
62 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
80impl<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 let hash =
488 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
489
490 self.history_by_block_hash(hash)
492 }
493 BlockNumberOrTag::Safe => {
494 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}