1use crate::{
2 BlockBodyIndicesProvider, BlockNumReader, HeaderProvider, ReceiptProvider,
3 ReceiptProviderIdExt, TransactionVariant, TransactionsProvider,
4};
5use alloc::{sync::Arc, vec::Vec};
6use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
7use alloy_primitives::{BlockNumber, TxNumber, B256};
8use core::ops::RangeInclusive;
9use reth_primitives_traits::{RecoveredBlock, SealedHeader};
10use reth_storage_errors::provider::ProviderResult;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
17pub enum BlockSource {
18 #[default]
23 Any,
24 Pending,
27 Canonical,
29}
30
31impl BlockSource {
32 pub const fn is_pending(&self) -> bool {
34 matches!(self, Self::Pending | Self::Any)
35 }
36
37 pub const fn is_canonical(&self) -> bool {
39 matches!(self, Self::Canonical | Self::Any)
40 }
41}
42
43pub type ProviderBlock<P> = <P as BlockReader>::Block;
45
46pub trait BlockReader:
51 BlockNumReader
52 + HeaderProvider
53 + BlockBodyIndicesProvider
54 + TransactionsProvider
55 + ReceiptProvider
56 + Send
57{
58 type Block: reth_primitives_traits::Block<
60 Body: reth_primitives_traits::BlockBody<Transaction = Self::Transaction>,
61 Header = Self::Header,
62 >;
63
64 fn find_block_by_hash(
70 &self,
71 hash: B256,
72 source: BlockSource,
73 ) -> ProviderResult<Option<Self::Block>>;
74
75 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>>;
79
80 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
85
86 #[expect(clippy::type_complexity)]
88 fn pending_block_and_receipts(
89 &self,
90 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>>;
91
92 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
96 self.block(hash.into())
97 }
98
99 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
103 self.block(num.into())
104 }
105
106 fn recovered_block(
112 &self,
113 id: BlockHashOrNumber,
114 transaction_kind: TransactionVariant,
115 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
116
117 fn sealed_block_with_senders(
123 &self,
124 id: BlockHashOrNumber,
125 transaction_kind: TransactionVariant,
126 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
127
128 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>>;
132
133 fn block_with_senders_range(
136 &self,
137 range: RangeInclusive<BlockNumber>,
138 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
139
140 fn recovered_block_range(
143 &self,
144 range: RangeInclusive<BlockNumber>,
145 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
146
147 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>>;
149}
150
151impl<T: BlockReader + Send + Sync> BlockReader for Arc<T> {
152 type Block = T::Block;
153
154 fn find_block_by_hash(
155 &self,
156 hash: B256,
157 source: BlockSource,
158 ) -> ProviderResult<Option<Self::Block>> {
159 T::find_block_by_hash(self, hash, source)
160 }
161 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
162 T::block(self, id)
163 }
164 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
165 T::pending_block(self)
166 }
167 fn pending_block_and_receipts(
168 &self,
169 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
170 T::pending_block_and_receipts(self)
171 }
172 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
173 T::block_by_hash(self, hash)
174 }
175 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
176 T::block_by_number(self, num)
177 }
178 fn recovered_block(
179 &self,
180 id: BlockHashOrNumber,
181 transaction_kind: TransactionVariant,
182 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
183 T::recovered_block(self, id, transaction_kind)
184 }
185 fn sealed_block_with_senders(
186 &self,
187 id: BlockHashOrNumber,
188 transaction_kind: TransactionVariant,
189 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
190 T::sealed_block_with_senders(self, id, transaction_kind)
191 }
192 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
193 T::block_range(self, range)
194 }
195 fn block_with_senders_range(
196 &self,
197 range: RangeInclusive<BlockNumber>,
198 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
199 T::block_with_senders_range(self, range)
200 }
201 fn recovered_block_range(
202 &self,
203 range: RangeInclusive<BlockNumber>,
204 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
205 T::recovered_block_range(self, range)
206 }
207 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
208 T::block_by_transaction_id(self, id)
209 }
210}
211
212impl<T: BlockReader + Send + Sync> BlockReader for &T {
213 type Block = T::Block;
214
215 fn find_block_by_hash(
216 &self,
217 hash: B256,
218 source: BlockSource,
219 ) -> ProviderResult<Option<Self::Block>> {
220 T::find_block_by_hash(self, hash, source)
221 }
222 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
223 T::block(self, id)
224 }
225 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
226 T::pending_block(self)
227 }
228 fn pending_block_and_receipts(
229 &self,
230 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
231 T::pending_block_and_receipts(self)
232 }
233 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
234 T::block_by_hash(self, hash)
235 }
236 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
237 T::block_by_number(self, num)
238 }
239 fn recovered_block(
240 &self,
241 id: BlockHashOrNumber,
242 transaction_kind: TransactionVariant,
243 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
244 T::recovered_block(self, id, transaction_kind)
245 }
246 fn sealed_block_with_senders(
247 &self,
248 id: BlockHashOrNumber,
249 transaction_kind: TransactionVariant,
250 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
251 T::sealed_block_with_senders(self, id, transaction_kind)
252 }
253 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
254 T::block_range(self, range)
255 }
256 fn block_with_senders_range(
257 &self,
258 range: RangeInclusive<BlockNumber>,
259 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
260 T::block_with_senders_range(self, range)
261 }
262 fn recovered_block_range(
263 &self,
264 range: RangeInclusive<BlockNumber>,
265 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
266 T::recovered_block_range(self, range)
267 }
268 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
269 T::block_by_transaction_id(self, id)
270 }
271}
272
273pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
284 fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Self::Block>> {
288 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
289 }
290
291 fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
296 self.sealed_header_by_id(BlockNumberOrTag::Pending.into())
297 }
298
299 fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
304 self.sealed_header_by_id(BlockNumberOrTag::Latest.into())
305 }
306
307 fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
312 self.sealed_header_by_id(BlockNumberOrTag::Safe.into())
313 }
314
315 fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
320 self.sealed_header_by_id(BlockNumberOrTag::Finalized.into())
321 }
322
323 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>>;
327
328 fn block_with_senders_by_id(
334 &self,
335 id: BlockId,
336 transaction_kind: TransactionVariant,
337 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
338 match id {
339 BlockId::Hash(hash) => self.recovered_block(hash.block_hash.into(), transaction_kind),
340 BlockId::Number(num) => self
341 .convert_block_number(num)?
342 .map_or_else(|| Ok(None), |num| self.recovered_block(num.into(), transaction_kind)),
343 }
344 }
345
346 fn header_by_number_or_tag(
350 &self,
351 id: BlockNumberOrTag,
352 ) -> ProviderResult<Option<Self::Header>> {
353 self.convert_block_number(id)?
354 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
355 }
356
357 fn sealed_header_by_number_or_tag(
361 &self,
362 id: BlockNumberOrTag,
363 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
364 self.convert_block_number(id)?
365 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
366 .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
367 }
368
369 fn sealed_header_by_id(
373 &self,
374 id: BlockId,
375 ) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
376
377 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
381}
382
383pub trait ChainStateBlockReader: Send {
385 fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
389 fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
393}
394
395pub trait ChainStateBlockWriter: Send {
397 fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
399
400 fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
402}