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, 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 + Sync
58{
59 type Block: reth_primitives_traits::Block<
61 Body: reth_primitives_traits::BlockBody<Transaction = Self::Transaction>,
62 Header = Self::Header,
63 >;
64
65 fn find_block_by_hash(
71 &self,
72 hash: B256,
73 source: BlockSource,
74 ) -> ProviderResult<Option<Self::Block>>;
75
76 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>>;
80
81 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
86
87 #[expect(clippy::type_complexity)]
89 fn pending_block_and_receipts(
90 &self,
91 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>>;
92
93 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
97 self.block(hash.into())
98 }
99
100 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
104 self.block(num.into())
105 }
106
107 fn recovered_block(
113 &self,
114 id: BlockHashOrNumber,
115 transaction_kind: TransactionVariant,
116 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
117
118 fn sealed_block_with_senders(
124 &self,
125 id: BlockHashOrNumber,
126 transaction_kind: TransactionVariant,
127 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
128
129 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>>;
133
134 fn block_with_senders_range(
137 &self,
138 range: RangeInclusive<BlockNumber>,
139 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
140
141 fn recovered_block_range(
144 &self,
145 range: RangeInclusive<BlockNumber>,
146 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
147}
148
149impl<T: BlockReader> BlockReader for Arc<T> {
150 type Block = T::Block;
151
152 fn find_block_by_hash(
153 &self,
154 hash: B256,
155 source: BlockSource,
156 ) -> ProviderResult<Option<Self::Block>> {
157 T::find_block_by_hash(self, hash, source)
158 }
159 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
160 T::block(self, id)
161 }
162 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
163 T::pending_block(self)
164 }
165 fn pending_block_and_receipts(
166 &self,
167 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
168 T::pending_block_and_receipts(self)
169 }
170 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
171 T::block_by_hash(self, hash)
172 }
173 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
174 T::block_by_number(self, num)
175 }
176 fn recovered_block(
177 &self,
178 id: BlockHashOrNumber,
179 transaction_kind: TransactionVariant,
180 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
181 T::recovered_block(self, id, transaction_kind)
182 }
183 fn sealed_block_with_senders(
184 &self,
185 id: BlockHashOrNumber,
186 transaction_kind: TransactionVariant,
187 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
188 T::sealed_block_with_senders(self, id, transaction_kind)
189 }
190 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
191 T::block_range(self, range)
192 }
193 fn block_with_senders_range(
194 &self,
195 range: RangeInclusive<BlockNumber>,
196 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
197 T::block_with_senders_range(self, range)
198 }
199 fn recovered_block_range(
200 &self,
201 range: RangeInclusive<BlockNumber>,
202 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
203 T::recovered_block_range(self, range)
204 }
205}
206
207impl<T: BlockReader> BlockReader for &T {
208 type Block = T::Block;
209
210 fn find_block_by_hash(
211 &self,
212 hash: B256,
213 source: BlockSource,
214 ) -> ProviderResult<Option<Self::Block>> {
215 T::find_block_by_hash(self, hash, source)
216 }
217 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
218 T::block(self, id)
219 }
220 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
221 T::pending_block(self)
222 }
223 fn pending_block_and_receipts(
224 &self,
225 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
226 T::pending_block_and_receipts(self)
227 }
228 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
229 T::block_by_hash(self, hash)
230 }
231 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
232 T::block_by_number(self, num)
233 }
234 fn recovered_block(
235 &self,
236 id: BlockHashOrNumber,
237 transaction_kind: TransactionVariant,
238 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
239 T::recovered_block(self, id, transaction_kind)
240 }
241 fn sealed_block_with_senders(
242 &self,
243 id: BlockHashOrNumber,
244 transaction_kind: TransactionVariant,
245 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
246 T::sealed_block_with_senders(self, id, transaction_kind)
247 }
248 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
249 T::block_range(self, range)
250 }
251 fn block_with_senders_range(
252 &self,
253 range: RangeInclusive<BlockNumber>,
254 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
255 T::block_with_senders_range(self, range)
256 }
257 fn recovered_block_range(
258 &self,
259 range: RangeInclusive<BlockNumber>,
260 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
261 T::recovered_block_range(self, range)
262 }
263}
264
265pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
276 fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Self::Block>> {
280 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
281 }
282
283 fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
288 self.sealed_header_by_id(BlockNumberOrTag::Pending.into())
289 }
290
291 fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
296 self.sealed_header_by_id(BlockNumberOrTag::Latest.into())
297 }
298
299 fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
304 self.sealed_header_by_id(BlockNumberOrTag::Safe.into())
305 }
306
307 fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
312 self.sealed_header_by_id(BlockNumberOrTag::Finalized.into())
313 }
314
315 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>>;
319
320 fn block_with_senders_by_id(
326 &self,
327 id: BlockId,
328 transaction_kind: TransactionVariant,
329 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
330 match id {
331 BlockId::Hash(hash) => self.recovered_block(hash.block_hash.into(), transaction_kind),
332 BlockId::Number(num) => self
333 .convert_block_number(num)?
334 .map_or_else(|| Ok(None), |num| self.recovered_block(num.into(), transaction_kind)),
335 }
336 }
337
338 fn header_by_number_or_tag(
342 &self,
343 id: BlockNumberOrTag,
344 ) -> ProviderResult<Option<Self::Header>> {
345 self.convert_block_number(id)?
346 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
347 }
348
349 fn sealed_header_by_number_or_tag(
353 &self,
354 id: BlockNumberOrTag,
355 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
356 self.convert_block_number(id)?
357 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
358 .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
359 }
360
361 fn sealed_header_by_id(
365 &self,
366 id: BlockId,
367 ) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
368
369 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
373}
374
375pub trait ChainStateBlockReader: Send + Sync {
377 fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
381 fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
385}
386
387pub trait ChainStateBlockWriter: Send + Sync {
389 fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
391
392 fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
394}