1use crate::{
2 BlockBodyIndicesProvider, HeaderProvider, ReceiptProvider, ReceiptProviderIdExt,
3 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_execution_types::RecoveredBlockAndExecutionOutput;
10use reth_primitives_traits::{Block as _, RecoveredBlock, SealedHeader, SealedOrRecoveredBlock};
11use reth_storage_errors::provider::ProviderResult;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
18pub enum BlockSource {
19 #[default]
24 Any,
25 Pending,
28 Canonical,
30}
31
32impl BlockSource {
33 pub const fn is_pending(&self) -> bool {
35 matches!(self, Self::Pending | Self::Any)
36 }
37
38 pub const fn is_canonical(&self) -> bool {
40 matches!(self, Self::Canonical | Self::Any)
41 }
42}
43
44pub type ProviderBlock<P> = <P as BlockReader>::Block;
46
47pub trait BlockReader:
52 HeaderProvider + BlockBodyIndicesProvider + TransactionsProvider + ReceiptProvider
53{
54 type Block: reth_primitives_traits::Block<
56 Body: reth_primitives_traits::BlockBody<Transaction = Self::Transaction>,
57 Header = Self::Header,
58 >;
59
60 fn find_block_by_hash(
66 &self,
67 hash: B256,
68 source: BlockSource,
69 ) -> ProviderResult<Option<Self::Block>>;
70
71 fn find_sealed_or_recovered_block(
80 &self,
81 hash: B256,
82 source: BlockSource,
83 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
84 self.find_block_by_hash(hash, source).map(|block| {
85 block.map(|block| SealedOrRecoveredBlock::sealed(block.seal_unchecked(hash)))
86 })
87 }
88
89 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>>;
93
94 fn pending_block(&self) -> ProviderResult<Option<Arc<RecoveredBlock<Self::Block>>>>;
99
100 fn pending_block_and_receipts(
102 &self,
103 ) -> ProviderResult<Option<RecoveredBlockAndExecutionOutput<Self::Block, Self::Receipt>>>;
104
105 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
109 self.block(hash.into())
110 }
111
112 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
116 self.block(num.into())
117 }
118
119 fn recovered_block(
125 &self,
126 id: BlockHashOrNumber,
127 transaction_kind: TransactionVariant,
128 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
129
130 fn sealed_block_with_senders(
136 &self,
137 id: BlockHashOrNumber,
138 transaction_kind: TransactionVariant,
139 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>>;
140
141 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>>;
145
146 fn block_with_senders_range(
149 &self,
150 range: RangeInclusive<BlockNumber>,
151 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
152
153 fn recovered_block_range(
156 &self,
157 range: RangeInclusive<BlockNumber>,
158 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>>;
159
160 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>>;
162}
163
164impl<T: BlockReader + Sync> BlockReader for Arc<T> {
165 type Block = T::Block;
166
167 fn find_block_by_hash(
168 &self,
169 hash: B256,
170 source: BlockSource,
171 ) -> ProviderResult<Option<Self::Block>> {
172 T::find_block_by_hash(self, hash, source)
173 }
174 fn find_sealed_or_recovered_block(
175 &self,
176 hash: B256,
177 source: BlockSource,
178 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
179 T::find_sealed_or_recovered_block(self, hash, source)
180 }
181 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
182 T::block(self, id)
183 }
184 fn pending_block(&self) -> ProviderResult<Option<Arc<RecoveredBlock<Self::Block>>>> {
185 T::pending_block(self)
186 }
187 fn pending_block_and_receipts(
188 &self,
189 ) -> ProviderResult<Option<RecoveredBlockAndExecutionOutput<Self::Block, Self::Receipt>>> {
190 T::pending_block_and_receipts(self)
191 }
192 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
193 T::block_by_hash(self, hash)
194 }
195 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
196 T::block_by_number(self, num)
197 }
198 fn recovered_block(
199 &self,
200 id: BlockHashOrNumber,
201 transaction_kind: TransactionVariant,
202 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
203 T::recovered_block(self, id, transaction_kind)
204 }
205 fn sealed_block_with_senders(
206 &self,
207 id: BlockHashOrNumber,
208 transaction_kind: TransactionVariant,
209 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
210 T::sealed_block_with_senders(self, id, transaction_kind)
211 }
212 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
213 T::block_range(self, range)
214 }
215 fn block_with_senders_range(
216 &self,
217 range: RangeInclusive<BlockNumber>,
218 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
219 T::block_with_senders_range(self, range)
220 }
221 fn recovered_block_range(
222 &self,
223 range: RangeInclusive<BlockNumber>,
224 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
225 T::recovered_block_range(self, range)
226 }
227 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
228 T::block_by_transaction_id(self, id)
229 }
230}
231
232impl<T: BlockReader + Sync> BlockReader for &T {
233 type Block = T::Block;
234
235 fn find_block_by_hash(
236 &self,
237 hash: B256,
238 source: BlockSource,
239 ) -> ProviderResult<Option<Self::Block>> {
240 T::find_block_by_hash(self, hash, source)
241 }
242 fn find_sealed_or_recovered_block(
243 &self,
244 hash: B256,
245 source: BlockSource,
246 ) -> ProviderResult<Option<SealedOrRecoveredBlock<Self::Block>>> {
247 T::find_sealed_or_recovered_block(self, hash, source)
248 }
249 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
250 T::block(self, id)
251 }
252 fn pending_block(&self) -> ProviderResult<Option<Arc<RecoveredBlock<Self::Block>>>> {
253 T::pending_block(self)
254 }
255 fn pending_block_and_receipts(
256 &self,
257 ) -> ProviderResult<Option<RecoveredBlockAndExecutionOutput<Self::Block, Self::Receipt>>> {
258 T::pending_block_and_receipts(self)
259 }
260 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
261 T::block_by_hash(self, hash)
262 }
263 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
264 T::block_by_number(self, num)
265 }
266 fn recovered_block(
267 &self,
268 id: BlockHashOrNumber,
269 transaction_kind: TransactionVariant,
270 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
271 T::recovered_block(self, id, transaction_kind)
272 }
273 fn sealed_block_with_senders(
274 &self,
275 id: BlockHashOrNumber,
276 transaction_kind: TransactionVariant,
277 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
278 T::sealed_block_with_senders(self, id, transaction_kind)
279 }
280 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
281 T::block_range(self, range)
282 }
283 fn block_with_senders_range(
284 &self,
285 range: RangeInclusive<BlockNumber>,
286 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
287 T::block_with_senders_range(self, range)
288 }
289 fn recovered_block_range(
290 &self,
291 range: RangeInclusive<BlockNumber>,
292 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
293 T::recovered_block_range(self, range)
294 }
295 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
296 T::block_by_transaction_id(self, id)
297 }
298}
299
300pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
311 fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Self::Block>> {
315 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
316 }
317
318 fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
323 self.sealed_header_by_id(BlockId::pending())
324 }
325
326 fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
331 self.sealed_header_by_id(BlockId::latest())
332 }
333
334 fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
339 self.sealed_header_by_id(BlockId::safe())
340 }
341
342 fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
347 self.sealed_header_by_id(BlockId::finalized())
348 }
349
350 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>>;
354
355 fn block_with_senders_by_id(
361 &self,
362 id: BlockId,
363 transaction_kind: TransactionVariant,
364 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
365 match id {
366 BlockId::Hash(hash) => self.recovered_block(hash.block_hash.into(), transaction_kind),
367 BlockId::Number(num) => self
368 .convert_block_number(num)?
369 .map_or_else(|| Ok(None), |num| self.recovered_block(num.into(), transaction_kind)),
370 }
371 }
372
373 fn header_by_number_or_tag(
377 &self,
378 id: BlockNumberOrTag,
379 ) -> ProviderResult<Option<Self::Header>> {
380 self.convert_block_number(id)?
381 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
382 }
383
384 fn sealed_header_by_number_or_tag(
388 &self,
389 id: BlockNumberOrTag,
390 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
391 self.convert_block_number(id)?
392 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
393 .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
394 }
395
396 fn sealed_header_by_id(
400 &self,
401 id: BlockId,
402 ) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
403
404 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
408}
409
410pub trait ChainStateBlockReader: Send {
412 fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
416 fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
420}
421
422pub trait ChainStateBlockWriter: Send {
424 fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
426
427 fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
429}