1use crate::{
2 BlockBodyIndicesProvider, BlockNumReader, HeaderProvider, OmmersProvider, ReceiptProvider,
3 ReceiptProviderIdExt, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
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, SealedBlock, 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 + WithdrawalsProvider
57 + OmmersProvider
58 + Send
59 + Sync
60{
61 type Block: reth_primitives_traits::Block<
63 Body: reth_primitives_traits::BlockBody<Transaction = Self::Transaction>,
64 Header = Self::Header,
65 >;
66
67 fn find_block_by_hash(
73 &self,
74 hash: B256,
75 source: BlockSource,
76 ) -> ProviderResult<Option<Self::Block>>;
77
78 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>>;
82
83 fn pending_block(&self) -> ProviderResult<Option<SealedBlock<Self::Block>>>;
88
89 fn pending_block_with_senders(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
94
95 #[allow(clippy::type_complexity)]
97 fn pending_block_and_receipts(
98 &self,
99 ) -> ProviderResult<Option<(SealedBlock<Self::Block>, Vec<Self::Receipt>)>>;
100
101 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
105 self.block(hash.into())
106 }
107
108 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
112 self.block(num.into())
113 }
114
115 fn recovered_block(
121 &self,
122 id: BlockHashOrNumber,
123 transaction_kind: TransactionVariant,
124 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
125
126 fn sealed_block_with_senders(
132 &self,
133 id: BlockHashOrNumber,
134 transaction_kind: TransactionVariant,
135 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
136
137 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>>;
141
142 fn block_with_senders_range(
145 &self,
146 range: RangeInclusive<BlockNumber>,
147 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
148
149 fn recovered_block_range(
152 &self,
153 range: RangeInclusive<BlockNumber>,
154 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
155}
156
157impl<T: BlockReader> BlockReader for Arc<T> {
158 type Block = T::Block;
159
160 fn find_block_by_hash(
161 &self,
162 hash: B256,
163 source: BlockSource,
164 ) -> ProviderResult<Option<Self::Block>> {
165 T::find_block_by_hash(self, hash, source)
166 }
167 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
168 T::block(self, id)
169 }
170 fn pending_block(&self) -> ProviderResult<Option<SealedBlock<Self::Block>>> {
171 T::pending_block(self)
172 }
173 fn pending_block_with_senders(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
174 T::pending_block_with_senders(self)
175 }
176 fn pending_block_and_receipts(
177 &self,
178 ) -> ProviderResult<Option<(SealedBlock<Self::Block>, Vec<Self::Receipt>)>> {
179 T::pending_block_and_receipts(self)
180 }
181 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
182 T::block_by_hash(self, hash)
183 }
184 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
185 T::block_by_number(self, num)
186 }
187 fn recovered_block(
188 &self,
189 id: BlockHashOrNumber,
190 transaction_kind: TransactionVariant,
191 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
192 T::recovered_block(self, id, transaction_kind)
193 }
194 fn sealed_block_with_senders(
195 &self,
196 id: BlockHashOrNumber,
197 transaction_kind: TransactionVariant,
198 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
199 T::sealed_block_with_senders(self, id, transaction_kind)
200 }
201 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
202 T::block_range(self, range)
203 }
204 fn block_with_senders_range(
205 &self,
206 range: RangeInclusive<BlockNumber>,
207 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
208 T::block_with_senders_range(self, range)
209 }
210 fn recovered_block_range(
211 &self,
212 range: RangeInclusive<BlockNumber>,
213 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
214 T::recovered_block_range(self, range)
215 }
216}
217
218impl<T: BlockReader> BlockReader for &T {
219 type Block = T::Block;
220
221 fn find_block_by_hash(
222 &self,
223 hash: B256,
224 source: BlockSource,
225 ) -> ProviderResult<Option<Self::Block>> {
226 T::find_block_by_hash(self, hash, source)
227 }
228 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
229 T::block(self, id)
230 }
231 fn pending_block(&self) -> ProviderResult<Option<SealedBlock<Self::Block>>> {
232 T::pending_block(self)
233 }
234 fn pending_block_with_senders(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
235 T::pending_block_with_senders(self)
236 }
237 fn pending_block_and_receipts(
238 &self,
239 ) -> ProviderResult<Option<(SealedBlock<Self::Block>, Vec<Self::Receipt>)>> {
240 T::pending_block_and_receipts(self)
241 }
242 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
243 T::block_by_hash(self, hash)
244 }
245 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
246 T::block_by_number(self, num)
247 }
248 fn recovered_block(
249 &self,
250 id: BlockHashOrNumber,
251 transaction_kind: TransactionVariant,
252 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
253 T::recovered_block(self, id, transaction_kind)
254 }
255 fn sealed_block_with_senders(
256 &self,
257 id: BlockHashOrNumber,
258 transaction_kind: TransactionVariant,
259 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
260 T::sealed_block_with_senders(self, id, transaction_kind)
261 }
262 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
263 T::block_range(self, range)
264 }
265 fn block_with_senders_range(
266 &self,
267 range: RangeInclusive<BlockNumber>,
268 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
269 T::block_with_senders_range(self, range)
270 }
271 fn recovered_block_range(
272 &self,
273 range: RangeInclusive<BlockNumber>,
274 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
275 T::recovered_block_range(self, range)
276 }
277}
278
279pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
290 fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Self::Block>> {
294 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
295 }
296
297 fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
302 self.sealed_header_by_id(BlockNumberOrTag::Pending.into())
303 }
304
305 fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
310 self.sealed_header_by_id(BlockNumberOrTag::Latest.into())
311 }
312
313 fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
318 self.sealed_header_by_id(BlockNumberOrTag::Safe.into())
319 }
320
321 fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
326 self.sealed_header_by_id(BlockNumberOrTag::Finalized.into())
327 }
328
329 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>>;
333
334 fn block_with_senders_by_id(
340 &self,
341 id: BlockId,
342 transaction_kind: TransactionVariant,
343 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
344 match id {
345 BlockId::Hash(hash) => self.recovered_block(hash.block_hash.into(), transaction_kind),
346 BlockId::Number(num) => self
347 .convert_block_number(num)?
348 .map_or_else(|| Ok(None), |num| self.recovered_block(num.into(), transaction_kind)),
349 }
350 }
351
352 fn header_by_number_or_tag(
356 &self,
357 id: BlockNumberOrTag,
358 ) -> ProviderResult<Option<Self::Header>> {
359 self.convert_block_number(id)?
360 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
361 }
362
363 fn sealed_header_by_number_or_tag(
367 &self,
368 id: BlockNumberOrTag,
369 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
370 self.convert_block_number(id)?
371 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
372 .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
373 }
374
375 fn sealed_header_by_id(
379 &self,
380 id: BlockId,
381 ) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
382
383 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
387
388 fn ommers_by_number_or_tag(
390 &self,
391 id: BlockNumberOrTag,
392 ) -> ProviderResult<Option<Vec<Self::Header>>> {
393 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.ommers(num.into()))
394 }
395
396 fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>>;
400}
401
402pub trait ChainStateBlockReader: Send + Sync {
404 fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
408 fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
412}
413
414pub trait ChainStateBlockWriter: Send + Sync {
416 fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
418
419 fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
421}