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