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 + 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 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>>;
150}
151
152impl<T: BlockReader> BlockReader for Arc<T> {
153 type Block = T::Block;
154
155 fn find_block_by_hash(
156 &self,
157 hash: B256,
158 source: BlockSource,
159 ) -> ProviderResult<Option<Self::Block>> {
160 T::find_block_by_hash(self, hash, source)
161 }
162 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
163 T::block(self, id)
164 }
165 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
166 T::pending_block(self)
167 }
168 fn pending_block_and_receipts(
169 &self,
170 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
171 T::pending_block_and_receipts(self)
172 }
173 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
174 T::block_by_hash(self, hash)
175 }
176 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
177 T::block_by_number(self, num)
178 }
179 fn recovered_block(
180 &self,
181 id: BlockHashOrNumber,
182 transaction_kind: TransactionVariant,
183 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
184 T::recovered_block(self, id, transaction_kind)
185 }
186 fn sealed_block_with_senders(
187 &self,
188 id: BlockHashOrNumber,
189 transaction_kind: TransactionVariant,
190 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
191 T::sealed_block_with_senders(self, id, transaction_kind)
192 }
193 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
194 T::block_range(self, range)
195 }
196 fn block_with_senders_range(
197 &self,
198 range: RangeInclusive<BlockNumber>,
199 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
200 T::block_with_senders_range(self, range)
201 }
202 fn recovered_block_range(
203 &self,
204 range: RangeInclusive<BlockNumber>,
205 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
206 T::recovered_block_range(self, range)
207 }
208 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
209 T::block_by_transaction_id(self, id)
210 }
211}
212
213impl<T: BlockReader> BlockReader for &T {
214 type Block = T::Block;
215
216 fn find_block_by_hash(
217 &self,
218 hash: B256,
219 source: BlockSource,
220 ) -> ProviderResult<Option<Self::Block>> {
221 T::find_block_by_hash(self, hash, source)
222 }
223 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
224 T::block(self, id)
225 }
226 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
227 T::pending_block(self)
228 }
229 fn pending_block_and_receipts(
230 &self,
231 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
232 T::pending_block_and_receipts(self)
233 }
234 fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
235 T::block_by_hash(self, hash)
236 }
237 fn block_by_number(&self, num: u64) -> ProviderResult<Option<Self::Block>> {
238 T::block_by_number(self, num)
239 }
240 fn recovered_block(
241 &self,
242 id: BlockHashOrNumber,
243 transaction_kind: TransactionVariant,
244 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
245 T::recovered_block(self, id, transaction_kind)
246 }
247 fn sealed_block_with_senders(
248 &self,
249 id: BlockHashOrNumber,
250 transaction_kind: TransactionVariant,
251 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
252 T::sealed_block_with_senders(self, id, transaction_kind)
253 }
254 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
255 T::block_range(self, range)
256 }
257 fn block_with_senders_range(
258 &self,
259 range: RangeInclusive<BlockNumber>,
260 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
261 T::block_with_senders_range(self, range)
262 }
263 fn recovered_block_range(
264 &self,
265 range: RangeInclusive<BlockNumber>,
266 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
267 T::recovered_block_range(self, range)
268 }
269 fn block_by_transaction_id(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
270 T::block_by_transaction_id(self, id)
271 }
272}
273
274pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
285 fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Self::Block>> {
289 self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
290 }
291
292 fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
297 self.sealed_header_by_id(BlockNumberOrTag::Pending.into())
298 }
299
300 fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
305 self.sealed_header_by_id(BlockNumberOrTag::Latest.into())
306 }
307
308 fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
313 self.sealed_header_by_id(BlockNumberOrTag::Safe.into())
314 }
315
316 fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
321 self.sealed_header_by_id(BlockNumberOrTag::Finalized.into())
322 }
323
324 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>>;
328
329 fn block_with_senders_by_id(
335 &self,
336 id: BlockId,
337 transaction_kind: TransactionVariant,
338 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
339 match id {
340 BlockId::Hash(hash) => self.recovered_block(hash.block_hash.into(), transaction_kind),
341 BlockId::Number(num) => self
342 .convert_block_number(num)?
343 .map_or_else(|| Ok(None), |num| self.recovered_block(num.into(), transaction_kind)),
344 }
345 }
346
347 fn header_by_number_or_tag(
351 &self,
352 id: BlockNumberOrTag,
353 ) -> ProviderResult<Option<Self::Header>> {
354 self.convert_block_number(id)?
355 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
356 }
357
358 fn sealed_header_by_number_or_tag(
362 &self,
363 id: BlockNumberOrTag,
364 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
365 self.convert_block_number(id)?
366 .map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
367 .map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
368 }
369
370 fn sealed_header_by_id(
374 &self,
375 id: BlockId,
376 ) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
377
378 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
382}
383
384pub trait ChainStateBlockReader: Send + Sync {
386 fn last_finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
390 fn last_safe_block_number(&self) -> ProviderResult<Option<BlockNumber>>;
394}
395
396pub trait ChainStateBlockWriter: Send + Sync {
398 fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
400
401 fn save_safe_block_number(&self, block_number: BlockNumber) -> ProviderResult<()>;
403}