mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: introduce StaticFileSegment::BlockMeta (#13226)
This commit is contained in:
@ -187,6 +187,7 @@ where
|
||||
headers: stages_checkpoints[0],
|
||||
receipts: stages_checkpoints[1],
|
||||
transactions: stages_checkpoints[2],
|
||||
block_meta: stages_checkpoints[2],
|
||||
};
|
||||
let targets = self.get_static_file_targets(highest_static_files)?;
|
||||
self.run(targets)?;
|
||||
@ -226,6 +227,9 @@ where
|
||||
finalized_block_number,
|
||||
)
|
||||
}),
|
||||
block_meta: finalized_block_numbers.block_meta.and_then(|finalized_block_number| {
|
||||
self.get_static_file_target(highest_static_files.block_meta, finalized_block_number)
|
||||
}),
|
||||
};
|
||||
|
||||
trace!(
|
||||
@ -322,6 +326,7 @@ mod tests {
|
||||
headers: Some(1),
|
||||
receipts: Some(1),
|
||||
transactions: Some(1),
|
||||
block_meta: None,
|
||||
})
|
||||
.expect("get static file targets");
|
||||
assert_eq!(
|
||||
@ -329,13 +334,19 @@ mod tests {
|
||||
StaticFileTargets {
|
||||
headers: Some(0..=1),
|
||||
receipts: Some(0..=1),
|
||||
transactions: Some(0..=1)
|
||||
transactions: Some(0..=1),
|
||||
block_meta: None
|
||||
}
|
||||
);
|
||||
assert_matches!(static_file_producer.run(targets), Ok(_));
|
||||
assert_eq!(
|
||||
provider_factory.static_file_provider().get_highest_static_files(),
|
||||
HighestStaticFiles { headers: Some(1), receipts: Some(1), transactions: Some(1) }
|
||||
HighestStaticFiles {
|
||||
headers: Some(1),
|
||||
receipts: Some(1),
|
||||
transactions: Some(1),
|
||||
block_meta: None
|
||||
}
|
||||
);
|
||||
|
||||
let targets = static_file_producer
|
||||
@ -343,6 +354,7 @@ mod tests {
|
||||
headers: Some(3),
|
||||
receipts: Some(3),
|
||||
transactions: Some(3),
|
||||
block_meta: None,
|
||||
})
|
||||
.expect("get static file targets");
|
||||
assert_eq!(
|
||||
@ -350,13 +362,19 @@ mod tests {
|
||||
StaticFileTargets {
|
||||
headers: Some(2..=3),
|
||||
receipts: Some(2..=3),
|
||||
transactions: Some(2..=3)
|
||||
transactions: Some(2..=3),
|
||||
block_meta: None
|
||||
}
|
||||
);
|
||||
assert_matches!(static_file_producer.run(targets), Ok(_));
|
||||
assert_eq!(
|
||||
provider_factory.static_file_provider().get_highest_static_files(),
|
||||
HighestStaticFiles { headers: Some(3), receipts: Some(3), transactions: Some(3) }
|
||||
HighestStaticFiles {
|
||||
headers: Some(3),
|
||||
receipts: Some(3),
|
||||
transactions: Some(3),
|
||||
block_meta: None
|
||||
}
|
||||
);
|
||||
|
||||
let targets = static_file_producer
|
||||
@ -364,6 +382,7 @@ mod tests {
|
||||
headers: Some(4),
|
||||
receipts: Some(4),
|
||||
transactions: Some(4),
|
||||
block_meta: None,
|
||||
})
|
||||
.expect("get static file targets");
|
||||
assert_eq!(
|
||||
@ -371,7 +390,8 @@ mod tests {
|
||||
StaticFileTargets {
|
||||
headers: Some(4..=4),
|
||||
receipts: Some(4..=4),
|
||||
transactions: Some(4..=4)
|
||||
transactions: Some(4..=4),
|
||||
block_meta: None
|
||||
}
|
||||
);
|
||||
assert_matches!(
|
||||
@ -380,7 +400,12 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
provider_factory.static_file_provider().get_highest_static_files(),
|
||||
HighestStaticFiles { headers: Some(3), receipts: Some(3), transactions: Some(3) }
|
||||
HighestStaticFiles {
|
||||
headers: Some(3),
|
||||
receipts: Some(3),
|
||||
transactions: Some(3),
|
||||
block_meta: None
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -408,6 +433,7 @@ mod tests {
|
||||
headers: Some(1),
|
||||
receipts: Some(1),
|
||||
transactions: Some(1),
|
||||
block_meta: None,
|
||||
})
|
||||
.expect("get static file targets");
|
||||
assert_matches!(locked_producer.run(targets.clone()), Ok(_));
|
||||
|
||||
@ -33,6 +33,9 @@ pub struct HighestStaticFiles {
|
||||
/// Highest static file block of transactions, inclusive.
|
||||
/// If [`None`], no static file is available.
|
||||
pub transactions: Option<BlockNumber>,
|
||||
/// Highest static file block of transactions, inclusive.
|
||||
/// If [`None`], no static file is available.
|
||||
pub block_meta: Option<BlockNumber>,
|
||||
}
|
||||
|
||||
impl HighestStaticFiles {
|
||||
@ -42,6 +45,7 @@ impl HighestStaticFiles {
|
||||
StaticFileSegment::Headers => self.headers,
|
||||
StaticFileSegment::Transactions => self.transactions,
|
||||
StaticFileSegment::Receipts => self.receipts,
|
||||
StaticFileSegment::BlockMeta => self.block_meta,
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,17 +55,23 @@ impl HighestStaticFiles {
|
||||
StaticFileSegment::Headers => &mut self.headers,
|
||||
StaticFileSegment::Transactions => &mut self.transactions,
|
||||
StaticFileSegment::Receipts => &mut self.receipts,
|
||||
StaticFileSegment::BlockMeta => &mut self.block_meta,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over all static file segments
|
||||
fn iter(&self) -> impl Iterator<Item = Option<BlockNumber>> {
|
||||
[self.headers, self.transactions, self.receipts, self.block_meta].into_iter()
|
||||
}
|
||||
|
||||
/// Returns the minimum block of all segments.
|
||||
pub fn min_block_num(&self) -> Option<u64> {
|
||||
[self.headers, self.transactions, self.receipts].iter().filter_map(|&option| option).min()
|
||||
self.iter().flatten().min()
|
||||
}
|
||||
|
||||
/// Returns the maximum block of all segments.
|
||||
pub fn max_block_num(&self) -> Option<u64> {
|
||||
[self.headers, self.transactions, self.receipts].iter().filter_map(|&option| option).max()
|
||||
self.iter().flatten().max()
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,12 +84,17 @@ pub struct StaticFileTargets {
|
||||
pub receipts: Option<RangeInclusive<BlockNumber>>,
|
||||
/// Targeted range of transactions.
|
||||
pub transactions: Option<RangeInclusive<BlockNumber>>,
|
||||
/// Targeted range of block meta.
|
||||
pub block_meta: Option<RangeInclusive<BlockNumber>>,
|
||||
}
|
||||
|
||||
impl StaticFileTargets {
|
||||
/// Returns `true` if any of the targets are [Some].
|
||||
pub const fn any(&self) -> bool {
|
||||
self.headers.is_some() || self.receipts.is_some() || self.transactions.is_some()
|
||||
self.headers.is_some() ||
|
||||
self.receipts.is_some() ||
|
||||
self.transactions.is_some() ||
|
||||
self.block_meta.is_some()
|
||||
}
|
||||
|
||||
/// Returns `true` if all targets are either [`None`] or has beginning of the range equal to the
|
||||
@ -89,6 +104,7 @@ impl StaticFileTargets {
|
||||
(self.headers.as_ref(), static_files.headers),
|
||||
(self.receipts.as_ref(), static_files.receipts),
|
||||
(self.transactions.as_ref(), static_files.transactions),
|
||||
(self.block_meta.as_ref(), static_files.block_meta),
|
||||
]
|
||||
.iter()
|
||||
.all(|(target_block_range, highest_static_fileted_block)| {
|
||||
@ -118,8 +134,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_highest_static_files_highest() {
|
||||
let files =
|
||||
HighestStaticFiles { headers: Some(100), receipts: Some(200), transactions: None };
|
||||
let files = HighestStaticFiles {
|
||||
headers: Some(100),
|
||||
receipts: Some(200),
|
||||
transactions: None,
|
||||
block_meta: None,
|
||||
};
|
||||
|
||||
// Test for headers segment
|
||||
assert_eq!(files.highest(StaticFileSegment::Headers), Some(100));
|
||||
@ -146,12 +166,20 @@ mod tests {
|
||||
// Modify transactions value
|
||||
*files.as_mut(StaticFileSegment::Transactions) = Some(350);
|
||||
assert_eq!(files.transactions, Some(350));
|
||||
|
||||
// Modify block meta value
|
||||
*files.as_mut(StaticFileSegment::BlockMeta) = Some(350);
|
||||
assert_eq!(files.block_meta, Some(350));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_highest_static_files_min() {
|
||||
let files =
|
||||
HighestStaticFiles { headers: Some(300), receipts: Some(100), transactions: None };
|
||||
let files = HighestStaticFiles {
|
||||
headers: Some(300),
|
||||
receipts: Some(100),
|
||||
transactions: None,
|
||||
block_meta: None,
|
||||
};
|
||||
|
||||
// Minimum value among the available segments
|
||||
assert_eq!(files.min_block_num(), Some(100));
|
||||
@ -163,8 +191,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_highest_static_files_max() {
|
||||
let files =
|
||||
HighestStaticFiles { headers: Some(300), receipts: Some(100), transactions: Some(500) };
|
||||
let files = HighestStaticFiles {
|
||||
headers: Some(300),
|
||||
receipts: Some(100),
|
||||
transactions: Some(500),
|
||||
block_meta: Some(500),
|
||||
};
|
||||
|
||||
// Maximum value among the available segments
|
||||
assert_eq!(files.max_block_num(), Some(500));
|
||||
|
||||
@ -3,7 +3,7 @@ use alloy_primitives::TxNumber;
|
||||
use derive_more::Display;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{ops::RangeInclusive, str::FromStr};
|
||||
use strum::{AsRefStr, EnumIter, EnumString};
|
||||
use strum::{AsRefStr, EnumString};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@ -17,7 +17,6 @@ use strum::{AsRefStr, EnumIter, EnumString};
|
||||
Deserialize,
|
||||
Serialize,
|
||||
EnumString,
|
||||
EnumIter,
|
||||
AsRefStr,
|
||||
Display,
|
||||
)]
|
||||
@ -34,6 +33,10 @@ pub enum StaticFileSegment {
|
||||
#[strum(serialize = "receipts")]
|
||||
/// Static File segment responsible for the `Receipts` table.
|
||||
Receipts,
|
||||
#[strum(serialize = "blockmeta")]
|
||||
/// Static File segment responsible for the `BlockBodyIndices`, `BlockOmmers`,
|
||||
/// `BlockWithdrawals` tables.
|
||||
BlockMeta,
|
||||
}
|
||||
|
||||
impl StaticFileSegment {
|
||||
@ -43,9 +46,17 @@ impl StaticFileSegment {
|
||||
Self::Headers => "headers",
|
||||
Self::Transactions => "transactions",
|
||||
Self::Receipts => "receipts",
|
||||
Self::BlockMeta => "blockmeta",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over all segments.
|
||||
pub fn iter() -> impl Iterator<Item = Self> {
|
||||
// The order of segments is significant and must be maintained to ensure correctness. For
|
||||
// example, Transactions require BlockBodyIndices from Blockmeta to be sound.
|
||||
[Self::Headers, Self::BlockMeta, Self::Transactions, Self::Receipts].into_iter()
|
||||
}
|
||||
|
||||
/// Returns the default configuration of the segment.
|
||||
pub const fn config(&self) -> SegmentConfig {
|
||||
SegmentConfig { compression: Compression::Lz4 }
|
||||
@ -54,7 +65,7 @@ impl StaticFileSegment {
|
||||
/// Returns the number of columns for the segment
|
||||
pub const fn columns(&self) -> usize {
|
||||
match self {
|
||||
Self::Headers => 3,
|
||||
Self::Headers | Self::BlockMeta => 3,
|
||||
Self::Transactions | Self::Receipts => 1,
|
||||
}
|
||||
}
|
||||
@ -118,16 +129,25 @@ impl StaticFileSegment {
|
||||
matches!(self, Self::Headers)
|
||||
}
|
||||
|
||||
/// Returns `true` if the segment is `StaticFileSegment::BlockMeta`.
|
||||
pub const fn is_block_meta(&self) -> bool {
|
||||
matches!(self, Self::BlockMeta)
|
||||
}
|
||||
|
||||
/// Returns `true` if the segment is `StaticFileSegment::Receipts`.
|
||||
pub const fn is_receipts(&self) -> bool {
|
||||
matches!(self, Self::Receipts)
|
||||
}
|
||||
|
||||
/// Returns `true` if the segment is `StaticFileSegment::Receipts` or
|
||||
/// `StaticFileSegment::Transactions`.
|
||||
/// Returns `true` if a segment row is linked to a transaction.
|
||||
pub const fn is_tx_based(&self) -> bool {
|
||||
matches!(self, Self::Receipts | Self::Transactions)
|
||||
}
|
||||
|
||||
/// Returns `true` if a segment row is linked to a block.
|
||||
pub const fn is_block_based(&self) -> bool {
|
||||
matches!(self, Self::Headers | Self::BlockMeta)
|
||||
}
|
||||
}
|
||||
|
||||
/// A segment header that contains information common to all segments. Used for storage.
|
||||
@ -228,40 +248,32 @@ impl SegmentHeader {
|
||||
|
||||
/// Increments tx end range depending on segment
|
||||
pub fn increment_tx(&mut self) {
|
||||
match self.segment {
|
||||
StaticFileSegment::Headers => (),
|
||||
StaticFileSegment::Transactions | StaticFileSegment::Receipts => {
|
||||
if let Some(tx_range) = &mut self.tx_range {
|
||||
tx_range.end += 1;
|
||||
} else {
|
||||
self.tx_range = Some(SegmentRangeInclusive::new(0, 0));
|
||||
}
|
||||
if self.segment.is_tx_based() {
|
||||
if let Some(tx_range) = &mut self.tx_range {
|
||||
tx_range.end += 1;
|
||||
} else {
|
||||
self.tx_range = Some(SegmentRangeInclusive::new(0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes `num` elements from end of tx or block range.
|
||||
pub fn prune(&mut self, num: u64) {
|
||||
match self.segment {
|
||||
StaticFileSegment::Headers => {
|
||||
if let Some(range) = &mut self.block_range {
|
||||
if num > range.end - range.start {
|
||||
self.block_range = None;
|
||||
} else {
|
||||
range.end = range.end.saturating_sub(num);
|
||||
}
|
||||
};
|
||||
if self.segment.is_block_based() {
|
||||
if let Some(range) = &mut self.block_range {
|
||||
if num > range.end - range.start {
|
||||
self.block_range = None;
|
||||
} else {
|
||||
range.end = range.end.saturating_sub(num);
|
||||
}
|
||||
};
|
||||
} else if let Some(range) = &mut self.tx_range {
|
||||
if num > range.end - range.start {
|
||||
self.tx_range = None;
|
||||
} else {
|
||||
range.end = range.end.saturating_sub(num);
|
||||
}
|
||||
StaticFileSegment::Transactions | StaticFileSegment::Receipts => {
|
||||
if let Some(range) = &mut self.tx_range {
|
||||
if num > range.end - range.start {
|
||||
self.tx_range = None;
|
||||
} else {
|
||||
range.end = range.end.saturating_sub(num);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets a new `block_range`.
|
||||
@ -286,10 +298,10 @@ impl SegmentHeader {
|
||||
|
||||
/// Returns the row offset which depends on whether the segment is block or transaction based.
|
||||
pub fn start(&self) -> Option<u64> {
|
||||
match self.segment {
|
||||
StaticFileSegment::Headers => self.block_start(),
|
||||
StaticFileSegment::Transactions | StaticFileSegment::Receipts => self.tx_start(),
|
||||
if self.segment.is_block_based() {
|
||||
return self.block_start()
|
||||
}
|
||||
self.tx_start()
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,7 +367,6 @@ mod tests {
|
||||
use super::*;
|
||||
use alloy_primitives::hex;
|
||||
use reth_nippy_jar::NippyJar;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
#[test]
|
||||
fn test_filename() {
|
||||
|
||||
Reference in New Issue
Block a user