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
18#[cfg(feature = "std")]
19mod changeset_offsets;
20#[cfg(feature = "std")]
21pub use changeset_offsets::{ChangesetOffsetReader, ChangesetOffsetWriter};
22
23use alloy_primitives::BlockNumber;
24pub use compression::Compression;
25use core::ops::RangeInclusive;
26pub use event::StaticFileProducerEvent;
27pub use segment::{
28 ChangesetOffset, SegmentConfig, SegmentHeader, SegmentRangeInclusive, StaticFileSegment,
29};
30
31pub type StaticFileMap<T> = alloc::boxed::Box<fixed_map::Map<StaticFileSegment, T>>;
33
34pub const DEFAULT_BLOCKS_PER_STATIC_FILE: u64 = 500_000;
36
37#[derive(Debug, Clone, Copy, Default, Eq, PartialEq)]
39pub struct HighestStaticFiles {
40 pub receipts: Option<BlockNumber>,
43}
44
45impl HighestStaticFiles {
46 fn iter(&self) -> impl Iterator<Item = Option<BlockNumber>> {
48 [self.receipts].into_iter()
49 }
50
51 pub fn min_block_num(&self) -> Option<u64> {
53 self.iter().flatten().min()
54 }
55
56 pub fn max_block_num(&self) -> Option<u64> {
58 self.iter().flatten().max()
59 }
60}
61
62#[derive(Debug, Clone, Eq, PartialEq)]
64pub struct StaticFileTargets {
65 pub receipts: Option<RangeInclusive<BlockNumber>>,
67}
68
69impl StaticFileTargets {
70 pub const fn any(&self) -> bool {
72 self.receipts.is_some()
73 }
74
75 pub fn is_contiguous_to_highest_static_files(&self, static_files: HighestStaticFiles) -> bool {
78 core::iter::once(&(self.receipts.as_ref(), static_files.receipts)).all(
79 |(target_block_range, highest_static_file_block)| {
80 target_block_range.is_none_or(|target_block_range| {
81 *target_block_range.start() ==
82 highest_static_file_block
83 .map_or(0, |highest_static_file_block| highest_static_file_block + 1)
84 })
85 },
86 )
87 }
88}
89
90pub const fn find_fixed_range(
93 block: BlockNumber,
94 blocks_per_static_file: u64,
95) -> SegmentRangeInclusive {
96 let start = (block / blocks_per_static_file) * blocks_per_static_file;
97 SegmentRangeInclusive::new(start, start + blocks_per_static_file - 1)
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_highest_static_files_min() {
106 let files = HighestStaticFiles { receipts: Some(100) };
107
108 assert_eq!(files.min_block_num(), Some(100));
110
111 let empty_files = HighestStaticFiles::default();
112 assert_eq!(empty_files.min_block_num(), None);
114 }
115
116 #[test]
117 fn test_highest_static_files_max() {
118 let files = HighestStaticFiles { receipts: Some(100) };
119
120 assert_eq!(files.max_block_num(), Some(100));
122
123 let empty_files = HighestStaticFiles::default();
124 assert_eq!(empty_files.max_block_num(), None);
126 }
127
128 #[test]
129 fn test_find_fixed_range() {
130 let block: BlockNumber = 600_000;
132 let range = find_fixed_range(block, DEFAULT_BLOCKS_PER_STATIC_FILE);
133 assert_eq!(range.start(), 500_000);
134 assert_eq!(range.end(), 999_999);
135
136 let block: BlockNumber = 1_200_000;
138 let range = find_fixed_range(block, 1_000_000);
139 assert_eq!(range.start(), 1_000_000);
140 assert_eq!(range.end(), 1_999_999);
141 }
142}