chore: deduplicate fork timestamp configuration in ChainSpec (#8038)

This commit is contained in:
0xKitsune
2024-05-01 14:00:57 -07:00
committed by GitHub
parent 0aa7d4d05e
commit 2334317dc7
5 changed files with 9 additions and 174 deletions

View File

@ -479,8 +479,8 @@ mod tests {
DatabaseEnv,
};
use reth_primitives::{
Chain, ForkTimestamps, Genesis, IntegerList, GOERLI, GOERLI_GENESIS_HASH, MAINNET,
MAINNET_GENESIS_HASH, SEPOLIA, SEPOLIA_GENESIS_HASH,
Chain, Genesis, IntegerList, GOERLI, GOERLI_GENESIS_HASH, MAINNET, MAINNET_GENESIS_HASH,
SEPOLIA, SEPOLIA_GENESIS_HASH,
};
use reth_provider::test_utils::create_test_provider_factory_with_chain_spec;
@ -570,7 +570,6 @@ mod tests {
..Default::default()
},
hardforks: BTreeMap::default(),
fork_timestamps: ForkTimestamps::default(),
genesis_hash: None,
paris_block_and_final_difficulty: None,
deposit_contract: None,

View File

@ -2,8 +2,7 @@ pub use alloy_chains::{Chain, ChainKind, NamedChain};
pub use info::ChainInfo;
pub use spec::{
AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder,
DisplayHardforks, ForkBaseFeeParams, ForkCondition, ForkTimestamps, DEV, GOERLI, HOLESKY,
MAINNET, SEPOLIA,
DisplayHardforks, ForkBaseFeeParams, ForkCondition, DEV, GOERLI, HOLESKY, MAINNET, SEPOLIA,
};
#[cfg(feature = "optimism")]
pub use spec::{BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA};

View File

@ -41,7 +41,6 @@ pub static MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
15537394,
U256::from(58_750_003_716_598_352_816_469u128),
)),
fork_timestamps: ForkTimestamps::default().shanghai(1681338455).cancun(1710338135),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
(Hardfork::Homestead, ForkCondition::Block(1150000)),
@ -90,7 +89,6 @@ pub static GOERLI: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
)),
// <https://goerli.etherscan.io/block/7382818>
paris_block_and_final_difficulty: Some((7382818, U256::from(10_790_000))),
fork_timestamps: ForkTimestamps::default().shanghai(1678832736).cancun(1705473120),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
(Hardfork::Homestead, ForkCondition::Block(0)),
@ -133,7 +131,6 @@ pub static SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
)),
// <https://sepolia.etherscan.io/block/1450409>
paris_block_and_final_difficulty: Some((1450409, U256::from(17_000_018_015_853_232u128))),
fork_timestamps: ForkTimestamps::default().shanghai(1677557088).cancun(1706655072),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
(Hardfork::Homestead, ForkCondition::Block(0)),
@ -179,7 +176,6 @@ pub static HOLESKY: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
"b5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4"
)),
paris_block_and_final_difficulty: Some((0, U256::from(1))),
fork_timestamps: ForkTimestamps::default().shanghai(1696000704).cancun(1707305664),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
(Hardfork::Homestead, ForkCondition::Block(0)),
@ -224,7 +220,6 @@ pub static DEV: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
"2f980576711e3617a5e4d83dd539548ec0f7792007d505a3d2e9674833af2d7c"
)),
paris_block_and_final_difficulty: Some((0, U256::from(0))),
fork_timestamps: ForkTimestamps::default().shanghai(0).cancun(0),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
(Hardfork::Homestead, ForkCondition::Block(0)),
@ -270,11 +265,6 @@ pub static OP_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
genesis_hash: Some(b256!(
"7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b"
)),
fork_timestamps: ForkTimestamps::default()
.shanghai(1704992401)
.canyon(1704992401)
.cancun(1710374401)
.ecotone(1710374401),
paris_block_and_final_difficulty: Some((0, U256::from(0))),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
@ -322,11 +312,6 @@ pub static OP_SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
genesis_hash: Some(b256!(
"102de6ffb001480cc9b8b548fd05c34cd4f46ae4aa91759393db90ea0409887d"
)),
fork_timestamps: ForkTimestamps::default()
.shanghai(1699981200)
.canyon(1699981200)
.cancun(1708534800)
.ecotone(1708534800),
paris_block_and_final_difficulty: Some((0, U256::from(0))),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
@ -376,11 +361,6 @@ pub static BASE_SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
genesis_hash: Some(b256!(
"0dcc9e089e30b90ddfc55be9a37dd15bc551aeee999d2e2b51414c54eaf934e4"
)),
fork_timestamps: ForkTimestamps::default()
.shanghai(1699981200)
.canyon(1699981200)
.cancun(1708534800)
.ecotone(1708534800),
paris_block_and_final_difficulty: Some((0, U256::from(0))),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
@ -430,11 +410,6 @@ pub static BASE_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
genesis_hash: Some(b256!(
"f712aa9241cc24369b143cf6dce85f0902a9731e70d66818a3a5845b296c73dd"
)),
fork_timestamps: ForkTimestamps::default()
.shanghai(1704992401)
.canyon(1704992401)
.cancun(1710374401)
.ecotone(1710374401),
paris_block_and_final_difficulty: Some((0, U256::from(0))),
hardforks: BTreeMap::from([
(Hardfork::Frontier, ForkCondition::Block(0)),
@ -535,12 +510,6 @@ pub struct ChainSpec {
#[serde(skip, default)]
pub paris_block_and_final_difficulty: Option<(u64, U256)>,
/// Timestamps of various hardforks
///
/// This caches entries in `hardforks` map
#[serde(skip, default)]
pub fork_timestamps: ForkTimestamps,
/// The active hard forks and their activation conditions
pub hardforks: BTreeMap<Hardfork, ForkCondition>,
@ -565,7 +534,6 @@ impl Default for ChainSpec {
genesis_hash: Default::default(),
genesis: Default::default(),
paris_block_and_final_difficulty: Default::default(),
fork_timestamps: Default::default(),
hardforks: Default::default(),
deposit_contract: Default::default(),
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
@ -819,28 +787,19 @@ impl ChainSpec {
/// Convenience method to check if [Hardfork::Shanghai] is active at a given timestamp.
#[inline]
pub fn is_shanghai_active_at_timestamp(&self, timestamp: u64) -> bool {
self.fork_timestamps
.shanghai
.map(|shanghai| timestamp >= shanghai)
.unwrap_or_else(|| self.is_fork_active_at_timestamp(Hardfork::Shanghai, timestamp))
self.is_fork_active_at_timestamp(Hardfork::Shanghai, timestamp)
}
/// Convenience method to check if [Hardfork::Cancun] is active at a given timestamp.
#[inline]
pub fn is_cancun_active_at_timestamp(&self, timestamp: u64) -> bool {
self.fork_timestamps
.cancun
.map(|cancun| timestamp >= cancun)
.unwrap_or_else(|| self.is_fork_active_at_timestamp(Hardfork::Cancun, timestamp))
self.is_fork_active_at_timestamp(Hardfork::Cancun, timestamp)
}
/// Convenience method to check if [Hardfork::Prague] is active at a given timestamp.
#[inline]
pub fn is_prague_active_at_timestamp(&self, timestamp: u64) -> bool {
self.fork_timestamps
.prague
.map(|prague| timestamp >= prague)
.unwrap_or_else(|| self.is_fork_active_at_timestamp(Hardfork::Prague, timestamp))
self.is_fork_active_at_timestamp(Hardfork::Prague, timestamp)
}
/// Convenience method to check if [Hardfork::Byzantium] is active at a given block number.
@ -1084,7 +1043,6 @@ impl From<Genesis> for ChainSpec {
chain: genesis.config.chain_id.into(),
genesis,
genesis_hash: None,
fork_timestamps: ForkTimestamps::from_hardforks(&hardforks),
hardforks,
paris_block_and_final_difficulty,
deposit_contract: None,
@ -1093,94 +1051,6 @@ impl From<Genesis> for ChainSpec {
}
}
/// Various timestamps of forks
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct ForkTimestamps {
/// The timestamp of the Shanghai fork
pub shanghai: Option<u64>,
/// The timestamp of the Cancun fork
pub cancun: Option<u64>,
/// The timestamp of the Prague fork
pub prague: Option<u64>,
/// The timestamp of the Regolith fork
#[cfg(feature = "optimism")]
pub regolith: Option<u64>,
/// The timestamp of the Canyon fork
#[cfg(feature = "optimism")]
pub canyon: Option<u64>,
/// The timestamp of the Ecotone fork
#[cfg(feature = "optimism")]
pub ecotone: Option<u64>,
}
impl ForkTimestamps {
/// Creates a new [`ForkTimestamps`] from the given hardforks by extracting the timestamps
fn from_hardforks(forks: &BTreeMap<Hardfork, ForkCondition>) -> Self {
let mut timestamps = ForkTimestamps::default();
if let Some(shanghai) = forks.get(&Hardfork::Shanghai).and_then(|f| f.as_timestamp()) {
timestamps = timestamps.shanghai(shanghai);
}
if let Some(cancun) = forks.get(&Hardfork::Cancun).and_then(|f| f.as_timestamp()) {
timestamps = timestamps.cancun(cancun);
}
if let Some(prague) = forks.get(&Hardfork::Prague).and_then(|f| f.as_timestamp()) {
timestamps = timestamps.prague(prague);
}
#[cfg(feature = "optimism")]
{
if let Some(regolith) = forks.get(&Hardfork::Regolith).and_then(|f| f.as_timestamp()) {
timestamps = timestamps.regolith(regolith);
}
if let Some(canyon) = forks.get(&Hardfork::Canyon).and_then(|f| f.as_timestamp()) {
timestamps = timestamps.canyon(canyon);
}
if let Some(ecotone) = forks.get(&Hardfork::Ecotone).and_then(|f| f.as_timestamp()) {
timestamps = timestamps.ecotone(ecotone);
}
}
timestamps
}
/// Sets the given Shanghai timestamp
pub fn shanghai(mut self, shanghai: u64) -> Self {
self.shanghai = Some(shanghai);
self
}
/// Sets the given Cancun timestamp
pub fn cancun(mut self, cancun: u64) -> Self {
self.cancun = Some(cancun);
self
}
/// Sets the given Prague timestamp
pub fn prague(mut self, prague: u64) -> Self {
self.prague = Some(prague);
self
}
/// Sets the given regolith timestamp
#[cfg(feature = "optimism")]
pub fn regolith(mut self, regolith: u64) -> Self {
self.regolith = Some(regolith);
self
}
/// Sets the given canyon timestamp
#[cfg(feature = "optimism")]
pub fn canyon(mut self, canyon: u64) -> Self {
self.canyon = Some(canyon);
self
}
/// Sets the given ecotone timestamp
#[cfg(feature = "optimism")]
pub fn ecotone(mut self, ecotone: u64) -> Self {
self.ecotone = Some(ecotone);
self
}
}
/// A helper type for compatibility with geth's config
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
@ -1418,7 +1288,6 @@ impl ChainSpecBuilder {
chain: self.chain.expect("The chain is required"),
genesis: self.genesis.expect("The genesis is required"),
genesis_hash: None,
fork_timestamps: ForkTimestamps::from_hardforks(&self.hardforks),
hardforks: self.hardforks,
paris_block_and_final_difficulty,
deposit_contract: None,
@ -1839,36 +1708,6 @@ Post-merge hard forks (timestamp based):
);
}
// Tests that the ForkTimestamps are correctly set up.
#[test]
fn test_fork_timestamps() {
let spec = ChainSpec::builder().chain(Chain::mainnet()).genesis(Genesis::default()).build();
assert!(spec.fork_timestamps.shanghai.is_none());
let spec = ChainSpec::builder()
.chain(Chain::mainnet())
.genesis(Genesis::default())
.with_fork(Hardfork::Shanghai, ForkCondition::Timestamp(1337))
.build();
assert_eq!(spec.fork_timestamps.shanghai, Some(1337));
assert!(spec.is_shanghai_active_at_timestamp(1337));
assert!(!spec.is_shanghai_active_at_timestamp(1336));
}
// Tests that all predefined timestamps are correctly set up in the chainspecs
#[test]
fn test_predefined_chain_spec_fork_timestamps() {
let predefined = [&MAINNET, &SEPOLIA, &HOLESKY, &GOERLI];
for spec in predefined.iter() {
let expected_timestamp_forks = &spec.fork_timestamps;
let got_timestamp_forks = ForkTimestamps::from_hardforks(&spec.hardforks);
// make sure they're the same
assert_eq!(expected_timestamp_forks, &got_timestamp_forks);
}
}
// Tests that we skip any fork blocks in block #0 (the genesis ruleset)
#[test]
fn ignores_genesis_fork_blocks() {

View File

@ -56,8 +56,8 @@ pub use block::{
};
pub use chain::{
AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, Chain, ChainInfo, ChainKind, ChainSpec,
ChainSpecBuilder, DisplayHardforks, ForkBaseFeeParams, ForkCondition, ForkTimestamps,
NamedChain, DEV, GOERLI, HOLESKY, MAINNET, SEPOLIA,
ChainSpecBuilder, DisplayHardforks, ForkBaseFeeParams, ForkCondition, NamedChain, DEV, GOERLI,
HOLESKY, MAINNET, SEPOLIA,
};
#[cfg(feature = "zstd-codec")]
pub use compression::*;