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