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