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/paradigmxyz/reth/issues/"
7)]
8#![cfg_attr(not(test), warn(unused_crate_dependencies))]
9#![cfg_attr(docsrs, feature(doc_cfg))]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12extern crate alloc;
13
14mod compression;
15mod event;
16mod segment;
17
18use alloy_primitives::BlockNumber;
19pub use compression::Compression;
20use core::ops::RangeInclusive;
21pub use event::StaticFileProducerEvent;
22pub use segment::{SegmentConfig, SegmentHeader, SegmentRangeInclusive, StaticFileSegment};
23
24pub const DEFAULT_BLOCKS_PER_STATIC_FILE: u64 = 500_000;
26
27#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
29pub struct HighestStaticFiles {
30 pub receipts: Option<BlockNumber>,
33}
34
35impl HighestStaticFiles {
36 fn iter(&self) -> impl Iterator<Item = Option<BlockNumber>> {
38 [self.receipts].into_iter()
39 }
40
41 pub fn min_block_num(&self) -> Option<u64> {
43 self.iter().flatten().min()
44 }
45
46 pub fn max_block_num(&self) -> Option<u64> {
48 self.iter().flatten().max()
49 }
50}
51
52#[derive(Debug, Clone, Eq, PartialEq)]
54pub struct StaticFileTargets {
55 pub receipts: Option<RangeInclusive<BlockNumber>>,
57}
58
59impl StaticFileTargets {
60 pub const fn any(&self) -> bool {
62 self.receipts.is_some()
63 }
64
65 pub fn is_contiguous_to_highest_static_files(&self, static_files: HighestStaticFiles) -> bool {
68 core::iter::once(&(self.receipts.as_ref(), static_files.receipts)).all(
69 |(target_block_range, highest_static_file_block)| {
70 target_block_range.is_none_or(|target_block_range| {
71 *target_block_range.start() ==
72 highest_static_file_block
73 .map_or(0, |highest_static_file_block| highest_static_file_block + 1)
74 })
75 },
76 )
77 }
78}
79
80pub const fn find_fixed_range(
83 block: BlockNumber,
84 blocks_per_static_file: u64,
85) -> SegmentRangeInclusive {
86 let start = (block / blocks_per_static_file) * blocks_per_static_file;
87 SegmentRangeInclusive::new(start, start + blocks_per_static_file - 1)
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_highest_static_files_min() {
96 let files = HighestStaticFiles { receipts: Some(100) };
97
98 assert_eq!(files.min_block_num(), Some(100));
100
101 let empty_files = HighestStaticFiles::default();
102 assert_eq!(empty_files.min_block_num(), None);
104 }
105
106 #[test]
107 fn test_highest_static_files_max() {
108 let files = HighestStaticFiles { receipts: Some(100) };
109
110 assert_eq!(files.max_block_num(), Some(100));
112
113 let empty_files = HighestStaticFiles::default();
114 assert_eq!(empty_files.max_block_num(), None);
116 }
117
118 #[test]
119 fn test_find_fixed_range() {
120 let block: BlockNumber = 600_000;
122 let range = find_fixed_range(block, DEFAULT_BLOCKS_PER_STATIC_FILE);
123 assert_eq!(range.start(), 500_000);
124 assert_eq!(range.end(), 999_999);
125
126 let block: BlockNumber = 1_200_000;
128 let range = find_fixed_range(block, 1_000_000);
129 assert_eq!(range.start(), 1_000_000);
130 assert_eq!(range.end(), 1_999_999);
131 }
132}