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