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::{Block as _, RecoveredBlock, SealedHeader, SealedOrRecoveredBlock};
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 find_sealed_or_recovered_block(
84 &self,
85 hash: B256,
86 source: BlockSource,
87 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
88 self.find_block_by_hash(hash, source).map(|block| {
89 block.map(|block| SealedOrRecoveredBlock::sealed(block.seal_unchecked(hash)))
90 })
91 }
92
93 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>>;
97
98 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
103
104 #[expect(clippy::type_complexity)]
106 fn pending_block_and_receipts(
107 &self,
108 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>>;
109
110 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
114 self.block(hash.into())
115 }
116
117 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
121 self.block(num.into())
122 }
123
124 fn recovered_block(
130 &self,
131 id: BlockHashOrNumber,
132 transaction_kind: TransactionVariant,
133 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
134
135 fn sealed_block_with_senders(
141 &self,
142 id: BlockHashOrNumber,
143 transaction_kind: TransactionVariant,
144 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
145
146 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>>;
150
151 fn block_with_senders_range(
154 &self,
155 range: RangeInclusive<BlockNumber>,
156 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
157
158 fn recovered_block_range(
161 &self,
162 range: RangeInclusive<BlockNumber>,
163 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
164
165 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>>;
167}
168
169impl<T: BlockReader + Send + Sync> BlockReader for Arc<T> {
170 type Block = T::Block;
171
172 fn find_block_by_hash(
173 &self,
174 hash: B256,
175 source: BlockSource,
176 ) -> ProviderResult<Option<Self::Block>> {
177 T::find_block_by_hash(self, hash, source)
178 }
179 fn find_sealed_or_recovered_block(
180 &self,
181 hash: B256,
182 source: BlockSource,
183 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
184 T::find_sealed_or_recovered_block(self, hash, source)
185 }
186 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
187 T::block(self, id)
188 }
189 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
190 T::pending_block(self)
191 }
192 fn pending_block_and_receipts(
193 &self,
194 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
195 T::pending_block_and_receipts(self)
196 }
197 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
198 T::block_by_hash(self, hash)
199 }
200 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
201 T::block_by_number(self, num)
202 }
203 fn recovered_block(
204 &self,
205 id: BlockHashOrNumber,
206 transaction_kind: TransactionVariant,
207 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
208 T::recovered_block(self, id, transaction_kind)
209 }
210 fn sealed_block_with_senders(
211 &self,
212 id: BlockHashOrNumber,
213 transaction_kind: TransactionVariant,
214 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
215 T::sealed_block_with_senders(self, id, transaction_kind)
216 }
217 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
218 T::block_range(self, range)
219 }
220 fn block_with_senders_range(
221 &self,
222 range: RangeInclusive<BlockNumber>,
223 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
224 T::block_with_senders_range(self, range)
225 }
226 fn recovered_block_range(
227 &self,
228 range: RangeInclusive<BlockNumber>,
229 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
230 T::recovered_block_range(self, range)
231 }
232 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
233 T::block_by_transaction_id(self, id)
234 }
235}
236
237impl<T: BlockReader + Send + Sync> BlockReader for &T {
238 type Block = T::Block;
239
240 fn find_block_by_hash(
241 &self,
242 hash: B256,
243 source: BlockSource,
244 ) -> ProviderResult<Option<Self::Block>> {
245 T::find_block_by_hash(self, hash, source)
246 }
247 fn find_sealed_or_recovered_block(
248 &self,
249 hash: B256,
250 source: BlockSource,
251 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
252 T::find_sealed_or_recovered_block(self, hash, source)
253 }
254 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
255 T::block(self, id)
256 }
257 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
258 T::pending_block(self)
259 }
260 fn pending_block_and_receipts(
261 &self,
262 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
263 T::pending_block_and_receipts(self)
264 }
265 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
266 T::block_by_hash(self, hash)
267 }
268 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
269 T::block_by_number(self, num)
270 }
271 fn recovered_block(
272 &self,
273 id: BlockHashOrNumber,
274 transaction_kind: TransactionVariant,
275 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
276 T::recovered_block(self, id, transaction_kind)
277 }
278 fn sealed_block_with_senders(
279 &self,
280 id: BlockHashOrNumber,
281 transaction_kind: TransactionVariant,
282 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
283 T::sealed_block_with_senders(self, id, transaction_kind)
284 }
285 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
286 T::block_range(self, range)
287 }
288 fn block_with_senders_range(
289 &self,
290 range: RangeInclusive<BlockNumber>,
291 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
292 T::block_with_senders_range(self, range)
293 }
294 fn recovered_block_range(
295 &self,
296 range: RangeInclusive<BlockNumber>,
297 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
298 T::recovered_block_range(self, range)
299 }
300 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
301 T::block_by_transaction_id(self, id)
302 }
303}
304
305pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
316 fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Self::Block>> {
320 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
321 }
322
323 fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
328 self.sealed_header_by_id(BlockNumberOrTag::Pending.into())
329 }
330
331 fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
336 self.sealed_header_by_id(BlockNumberOrTag::Latest.into())
337 }
338
339 fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
344 self.sealed_header_by_id(BlockNumberOrTag::Safe.into())
345 }
346
347 fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
352 self.sealed_header_by_id(BlockNumberOrTag::Finalized.into())
353 }
354
355 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>>;
359
360 fn block_with_senders_by_id(
366 &self,
367 id: BlockId,
368 transaction_kind: TransactionVariant,
369 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
370 match id {
371 BlockId::Hash(hash) => self.recovered_block(hash.block_hash.into(), transaction_kind),
372 BlockId::Number(num) => self
373 .convert_block_number(num)?
374 .map_or_else(|| Ok(None), |num| self.recovered_block(num.into(), transaction_kind)),
375 }
376 }
377
378 fn header_by_number_or_tag(
382 &self,
383 id: BlockNumberOrTag,
384 ) -> ProviderResult<Option<Self::Header>> {
385 self.convert_block_number(id)?
386 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
387 }
388
389 fn sealed_header_by_number_or_tag(
393 &self,
394 id: BlockNumberOrTag,
395 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
396 self.convert_block_number(id)?
397 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
398 .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
399 }
400
401 fn sealed_header_by_id(
405 &self,
406 id: BlockId,
407 ) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
408
409 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
413}
414
415pub trait ChainStateBlockReader: Send {
417 fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
421 fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
425}
426
427pub trait ChainStateBlockWriter: Send {
429 fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
431
432 fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
434}