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