reth_provider/providers/static_file/
jar.rs1use super::{
2 metrics::{StaticFileProviderMetrics, StaticFileProviderOperation},
3 LoadedJarRef,
4};
5use crate::{
6 to_range, BlockHashReader, BlockNumReader, HeaderProvider, ReceiptProvider,
7 TransactionsProvider,
8};
9use alloy_consensus::transaction::{SignerRecoverable, TransactionMeta};
10use alloy_eips::{eip2718::Encodable2718, BlockHashOrNumber};
11use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
12use reth_chainspec::ChainInfo;
13use reth_db::static_file::{
14 BlockHashMask, HeaderMask, HeaderWithHashMask, ReceiptMask, StaticFileCursor, TDWithHashMask,
15 TotalDifficultyMask, TransactionMask,
16};
17use reth_db_api::table::{Decompress, Value};
18use reth_node_types::NodePrimitives;
19use reth_primitives_traits::{SealedHeader, SignedTransaction};
20use reth_storage_errors::provider::{ProviderError, ProviderResult};
21use std::{
22 fmt::Debug,
23 ops::{Deref, RangeBounds, RangeInclusive},
24 sync::Arc,
25};
26#[derive(Debug)]
28pub struct StaticFileJarProvider<'a, N> {
29 jar: LoadedJarRef<'a>,
31 auxiliary_jar: Option<Box<Self>>,
33 metrics: Option<Arc<StaticFileProviderMetrics>>,
35 _pd: std::marker::PhantomData<N>,
37}
38
39impl<'a, N: NodePrimitives> Deref for StaticFileJarProvider<'a, N> {
40 type Target = LoadedJarRef<'a>;
41 fn deref(&self) -> &Self::Target {
42 &self.jar
43 }
44}
45
46impl<'a, N: NodePrimitives> From<LoadedJarRef<'a>> for StaticFileJarProvider<'a, N> {
47 fn from(value: LoadedJarRef<'a>) -> Self {
48 StaticFileJarProvider {
49 jar: value,
50 auxiliary_jar: None,
51 metrics: None,
52 _pd: Default::default(),
53 }
54 }
55}
56
57impl<'a, N: NodePrimitives> StaticFileJarProvider<'a, N> {
58 pub fn cursor<'b>(&'b self) -> ProviderResult<StaticFileCursor<'a>>
60 where
61 'b: 'a,
62 {
63 let result = StaticFileCursor::new(self.value(), self.mmap_handle())?;
64
65 if let Some(metrics) = &self.metrics {
66 metrics.record_segment_operation(
67 self.segment(),
68 StaticFileProviderOperation::InitCursor,
69 None,
70 );
71 }
72
73 Ok(result)
74 }
75
76 pub fn with_auxiliary(mut self, auxiliary_jar: Self) -> Self {
78 self.auxiliary_jar = Some(Box::new(auxiliary_jar));
79 self
80 }
81
82 pub fn with_metrics(mut self, metrics: Arc<StaticFileProviderMetrics>) -> Self {
84 self.metrics = Some(metrics);
85 self
86 }
87}
88
89impl<N: NodePrimitives<BlockHeader: Value>> HeaderProvider for StaticFileJarProvider<'_, N> {
90 type Header = N::BlockHeader;
91
92 fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
93 Ok(self
94 .cursor()?
95 .get_two::<HeaderWithHashMask<Self::Header>>(block_hash.into())?
96 .filter(|(_, hash)| hash == block_hash)
97 .map(|(header, _)| header))
98 }
99
100 fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
101 self.cursor()?.get_one::<HeaderMask<Self::Header>>(num.into())
102 }
103
104 fn header_td(&self, block_hash: &BlockHash) -> ProviderResult<Option<U256>> {
105 Ok(self
106 .cursor()?
107 .get_two::<TDWithHashMask>(block_hash.into())?
108 .filter(|(_, hash)| hash == block_hash)
109 .map(|(td, _)| td.into()))
110 }
111
112 fn header_td_by_number(&self, num: BlockNumber) -> ProviderResult<Option<U256>> {
113 Ok(self.cursor()?.get_one::<TotalDifficultyMask>(num.into())?.map(Into::into))
114 }
115
116 fn headers_range(
117 &self,
118 range: impl RangeBounds<BlockNumber>,
119 ) -> ProviderResult<Vec<Self::Header>> {
120 let range = to_range(range);
121
122 let mut cursor = self.cursor()?;
123 let mut headers = Vec::with_capacity((range.end - range.start) as usize);
124
125 for num in range {
126 if let Some(header) = cursor.get_one::<HeaderMask<Self::Header>>(num.into())? {
127 headers.push(header);
128 }
129 }
130
131 Ok(headers)
132 }
133
134 fn sealed_header(
135 &self,
136 number: BlockNumber,
137 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
138 Ok(self
139 .cursor()?
140 .get_two::<HeaderWithHashMask<Self::Header>>(number.into())?
141 .map(|(header, hash)| SealedHeader::new(header, hash)))
142 }
143
144 fn sealed_headers_while(
145 &self,
146 range: impl RangeBounds<BlockNumber>,
147 mut predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
148 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
149 let range = to_range(range);
150
151 let mut cursor = self.cursor()?;
152 let mut headers = Vec::with_capacity((range.end - range.start) as usize);
153
154 for number in range {
155 if let Some((header, hash)) =
156 cursor.get_two::<HeaderWithHashMask<Self::Header>>(number.into())?
157 {
158 let sealed = SealedHeader::new(header, hash);
159 if !predicate(&sealed) {
160 break
161 }
162 headers.push(sealed);
163 }
164 }
165 Ok(headers)
166 }
167}
168
169impl<N: NodePrimitives> BlockHashReader for StaticFileJarProvider<'_, N> {
170 fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
171 self.cursor()?.get_one::<BlockHashMask>(number.into())
172 }
173
174 fn canonical_hashes_range(
175 &self,
176 start: BlockNumber,
177 end: BlockNumber,
178 ) -> ProviderResult<Vec<B256>> {
179 let mut cursor = self.cursor()?;
180 let mut hashes = Vec::with_capacity((end - start) as usize);
181
182 for number in start..end {
183 if let Some(hash) = cursor.get_one::<BlockHashMask>(number.into())? {
184 hashes.push(hash)
185 }
186 }
187 Ok(hashes)
188 }
189}
190
191impl<N: NodePrimitives> BlockNumReader for StaticFileJarProvider<'_, N> {
192 fn chain_info(&self) -> ProviderResult<ChainInfo> {
193 Err(ProviderError::UnsupportedProvider)
195 }
196
197 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
198 Err(ProviderError::UnsupportedProvider)
200 }
201
202 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
203 Err(ProviderError::UnsupportedProvider)
205 }
206
207 fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>> {
208 let mut cursor = self.cursor()?;
209
210 Ok(cursor
211 .get_one::<BlockHashMask>((&hash).into())?
212 .and_then(|res| (res == hash).then(|| cursor.number()).flatten()))
213 }
214}
215
216impl<N: NodePrimitives<SignedTx: Decompress + SignedTransaction>> TransactionsProvider
217 for StaticFileJarProvider<'_, N>
218{
219 type Transaction = N::SignedTx;
220
221 fn transaction_id(&self, hash: TxHash) -> ProviderResult<Option<TxNumber>> {
222 let mut cursor = self.cursor()?;
223
224 Ok(cursor
225 .get_one::<TransactionMask<Self::Transaction>>((&hash).into())?
226 .and_then(|res| (res.trie_hash() == hash).then(|| cursor.number()).flatten()))
227 }
228
229 fn transaction_by_id(&self, num: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
230 self.cursor()?.get_one::<TransactionMask<Self::Transaction>>(num.into())
231 }
232
233 fn transaction_by_id_unhashed(
234 &self,
235 num: TxNumber,
236 ) -> ProviderResult<Option<Self::Transaction>> {
237 self.cursor()?.get_one::<TransactionMask<Self::Transaction>>(num.into())
238 }
239
240 fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
241 self.cursor()?.get_one::<TransactionMask<Self::Transaction>>((&hash).into())
242 }
243
244 fn transaction_by_hash_with_meta(
245 &self,
246 _hash: TxHash,
247 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
248 Err(ProviderError::UnsupportedProvider)
250 }
251
252 fn transaction_block(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
253 Err(ProviderError::UnsupportedProvider)
255 }
256
257 fn transactions_by_block(
258 &self,
259 _block_id: BlockHashOrNumber,
260 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
261 Err(ProviderError::UnsupportedProvider)
264 }
265
266 fn transactions_by_block_range(
267 &self,
268 _range: impl RangeBounds<BlockNumber>,
269 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
270 Err(ProviderError::UnsupportedProvider)
273 }
274
275 fn transactions_by_tx_range(
276 &self,
277 range: impl RangeBounds<TxNumber>,
278 ) -> ProviderResult<Vec<Self::Transaction>> {
279 let range = to_range(range);
280 let mut cursor = self.cursor()?;
281 let mut txes = Vec::with_capacity((range.end - range.start) as usize);
282
283 for num in range {
284 if let Some(tx) = cursor.get_one::<TransactionMask<Self::Transaction>>(num.into())? {
285 txes.push(tx)
286 }
287 }
288 Ok(txes)
289 }
290
291 fn senders_by_tx_range(
292 &self,
293 range: impl RangeBounds<TxNumber>,
294 ) -> ProviderResult<Vec<Address>> {
295 let txs = self.transactions_by_tx_range(range)?;
296 Ok(reth_primitives_traits::transaction::recover::recover_signers(&txs)?)
297 }
298
299 fn transaction_sender(&self, num: TxNumber) -> ProviderResult<Option<Address>> {
300 Ok(self
301 .cursor()?
302 .get_one::<TransactionMask<Self::Transaction>>(num.into())?
303 .and_then(|tx| tx.recover_signer().ok()))
304 }
305}
306
307impl<N: NodePrimitives<SignedTx: Decompress + SignedTransaction, Receipt: Decompress>>
308 ReceiptProvider for StaticFileJarProvider<'_, N>
309{
310 type Receipt = N::Receipt;
311
312 fn receipt(&self, num: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
313 self.cursor()?.get_one::<ReceiptMask<Self::Receipt>>(num.into())
314 }
315
316 fn receipt_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
317 if let Some(tx_static_file) = &self.auxiliary_jar {
318 if let Some(num) = tx_static_file.transaction_id(hash)? {
319 return self.receipt(num)
320 }
321 }
322 Ok(None)
323 }
324
325 fn receipts_by_block(
326 &self,
327 _block: BlockHashOrNumber,
328 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
329 Err(ProviderError::UnsupportedProvider)
332 }
333
334 fn receipts_by_tx_range(
335 &self,
336 range: impl RangeBounds<TxNumber>,
337 ) -> ProviderResult<Vec<Self::Receipt>> {
338 let range = to_range(range);
339 let mut cursor = self.cursor()?;
340 let mut receipts = Vec::with_capacity((range.end - range.start) as usize);
341
342 for num in range {
343 if let Some(tx) = cursor.get_one::<ReceiptMask<Self::Receipt>>(num.into())? {
344 receipts.push(tx)
345 }
346 }
347 Ok(receipts)
348 }
349
350 fn receipts_by_block_range(
351 &self,
352 _block_range: RangeInclusive<BlockNumber>,
353 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
354 Err(ProviderError::UnsupportedProvider)
357 }
358}