feat: introduce StaticFileSegment::BlockMeta (#13226)

This commit is contained in:
joshieDo
2025-01-14 23:47:28 +00:00
committed by GitHub
parent 46f4d73c4d
commit 1267718c7e
10 changed files with 346 additions and 111 deletions

View File

@ -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(_));

View File

@ -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));

View File

@ -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() {