reth_static_file_types/
lib.rs1#![doc(
4 html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
5 html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
6 issue_tracker_base_url = "https://github.com/SeismicSystems/seismic-reth/issues/"
7)]
8#![cfg_attr(not(test), warn(unused_crate_dependencies))]
9#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
10
11mod compression;
12mod event;
13mod segment;
14
15use alloy_primitives::BlockNumber;
16pub use compression::Compression;
17pub use event::StaticFileProducerEvent;
18pub use segment::{SegmentConfig, SegmentHeader, SegmentRangeInclusive, StaticFileSegment};
19use std::ops::RangeInclusive;
20
21pub const DEFAULT_BLOCKS_PER_STATIC_FILE: u64 = 500_000;
23
24#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
26pub struct HighestStaticFiles {
27 pub headers: Option<BlockNumber>,
30 pub receipts: Option<BlockNumber>,
33 pub transactions: Option<BlockNumber>,
36}
37
38impl HighestStaticFiles {
39 pub const fn highest(&self, segment: StaticFileSegment) -> Option<BlockNumber> {
41 match segment {
42 StaticFileSegment::Headers => self.headers,
43 StaticFileSegment::Transactions => self.transactions,
44 StaticFileSegment::Receipts => self.receipts,
45 }
46 }
47
48 pub fn as_mut(&mut self, segment: StaticFileSegment) -> &mut Option<BlockNumber> {
50 match segment {
51 StaticFileSegment::Headers => &mut self.headers,
52 StaticFileSegment::Transactions => &mut self.transactions,
53 StaticFileSegment::Receipts => &mut self.receipts,
54 }
55 }
56
57 pub fn min_block_num(&self) -> Option<u64> {
59 [self.headers, self.transactions, self.receipts].iter().filter_map(|&option| option).min()
60 }
61
62 pub fn max_block_num(&self) -> Option<u64> {
64 [self.headers, self.transactions, self.receipts].iter().filter_map(|&option| option).max()
65 }
66}
67
68#[derive(Debug, Clone, Eq, PartialEq)]
70pub struct StaticFileTargets {
71 pub headers: Option<RangeInclusive<BlockNumber>>,
73 pub receipts: Option<RangeInclusive<BlockNumber>>,
75 pub transactions: Option<RangeInclusive<BlockNumber>>,
77}
78
79impl StaticFileTargets {
80 pub const fn any(&self) -> bool {
82 self.headers.is_some() || self.receipts.is_some() || self.transactions.is_some()
83 }
84
85 pub fn is_contiguous_to_highest_static_files(&self, static_files: HighestStaticFiles) -> bool {
88 [
89 (self.headers.as_ref(), static_files.headers),
90 (self.receipts.as_ref(), static_files.receipts),
91 (self.transactions.as_ref(), static_files.transactions),
92 ]
93 .iter()
94 .all(|(target_block_range, highest_static_fileted_block)| {
95 target_block_range.is_none_or(|target_block_range| {
96 *target_block_range.start() ==
97 highest_static_fileted_block.map_or(0, |highest_static_fileted_block| {
98 highest_static_fileted_block + 1
99 })
100 })
101 })
102 }
103}
104
105pub const fn find_fixed_range(
108 block: BlockNumber,
109 blocks_per_static_file: u64,
110) -> SegmentRangeInclusive {
111 let start = (block / blocks_per_static_file) * blocks_per_static_file;
112 SegmentRangeInclusive::new(start, start + blocks_per_static_file - 1)
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_highest_static_files_highest() {
121 let files =
122 HighestStaticFiles { headers: Some(100), receipts: Some(200), transactions: None };
123
124 assert_eq!(files.highest(StaticFileSegment::Headers), Some(100));
126
127 assert_eq!(files.highest(StaticFileSegment::Receipts), Some(200));
129
130 assert_eq!(files.highest(StaticFileSegment::Transactions), None);
132 }
133
134 #[test]
135 fn test_highest_static_files_as_mut() {
136 let mut files = HighestStaticFiles::default();
137
138 *files.as_mut(StaticFileSegment::Headers) = Some(150);
140 assert_eq!(files.headers, Some(150));
141
142 *files.as_mut(StaticFileSegment::Receipts) = Some(250);
144 assert_eq!(files.receipts, Some(250));
145
146 *files.as_mut(StaticFileSegment::Transactions) = Some(350);
148 assert_eq!(files.transactions, Some(350));
149 }
150
151 #[test]
152 fn test_highest_static_files_min() {
153 let files =
154 HighestStaticFiles { headers: Some(300), receipts: Some(100), transactions: None };
155
156 assert_eq!(files.min_block_num(), Some(100));
158
159 let empty_files = HighestStaticFiles::default();
160 assert_eq!(empty_files.min_block_num(), None);
162 }
163
164 #[test]
165 fn test_highest_static_files_max() {
166 let files =
167 HighestStaticFiles { headers: Some(300), receipts: Some(100), transactions: Some(500) };
168
169 assert_eq!(files.max_block_num(), Some(500));
171
172 let empty_files = HighestStaticFiles::default();
173 assert_eq!(empty_files.max_block_num(), None);
175 }
176
177 #[test]
178 fn test_find_fixed_range() {
179 let block: BlockNumber = 600_000;
181 let range = find_fixed_range(block, DEFAULT_BLOCKS_PER_STATIC_FILE);
182 assert_eq!(range.start(), 500_000);
183 assert_eq!(range.end(), 999_999);
184
185 let block: BlockNumber = 1_200_000;
187 let range = find_fixed_range(block, 1_000_000);
188 assert_eq!(range.start(), 1_000_000);
189 assert_eq!(range.end(), 1_999_999);
190 }
191}