mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
perf: cache fork timestamps (#2886)
This commit is contained in:
@ -20,6 +20,7 @@ pub static MAINNET: Lazy<ChainSpec> = Lazy::new(|| ChainSpec {
|
|||||||
genesis_hash: Some(H256(hex!(
|
genesis_hash: Some(H256(hex!(
|
||||||
"d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
|
"d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
|
||||||
))),
|
))),
|
||||||
|
fork_timestamps: ForkTimestamps::default().shanghai(1681338455),
|
||||||
hardforks: BTreeMap::from([
|
hardforks: BTreeMap::from([
|
||||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||||
(Hardfork::Homestead, ForkCondition::Block(1150000)),
|
(Hardfork::Homestead, ForkCondition::Block(1150000)),
|
||||||
@ -54,6 +55,7 @@ pub static GOERLI: Lazy<ChainSpec> = Lazy::new(|| ChainSpec {
|
|||||||
genesis_hash: Some(H256(hex!(
|
genesis_hash: Some(H256(hex!(
|
||||||
"bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"
|
"bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"
|
||||||
))),
|
))),
|
||||||
|
fork_timestamps: ForkTimestamps::default().shanghai(1678832736),
|
||||||
hardforks: BTreeMap::from([
|
hardforks: BTreeMap::from([
|
||||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||||
@ -82,6 +84,7 @@ pub static SEPOLIA: Lazy<ChainSpec> = Lazy::new(|| ChainSpec {
|
|||||||
genesis_hash: Some(H256(hex!(
|
genesis_hash: Some(H256(hex!(
|
||||||
"25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"
|
"25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"
|
||||||
))),
|
))),
|
||||||
|
fork_timestamps: ForkTimestamps::default().shanghai(1677557088),
|
||||||
hardforks: BTreeMap::from([
|
hardforks: BTreeMap::from([
|
||||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||||
@ -128,6 +131,12 @@ pub struct ChainSpec {
|
|||||||
/// The genesis block
|
/// The genesis block
|
||||||
pub genesis: Genesis,
|
pub genesis: Genesis,
|
||||||
|
|
||||||
|
/// 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
|
/// The active hard forks and their activation conditions
|
||||||
pub hardforks: BTreeMap<Hardfork, ForkCondition>,
|
pub hardforks: BTreeMap<Hardfork, ForkCondition>,
|
||||||
}
|
}
|
||||||
@ -210,7 +219,10 @@ impl ChainSpec {
|
|||||||
/// Convenience method to check if [Hardfork::Shanghai] is active at a given timestamp.
|
/// Convenience method to check if [Hardfork::Shanghai] is active at a given timestamp.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_shanghai_activated_at_timestamp(&self, timestamp: u64) -> bool {
|
pub fn is_shanghai_activated_at_timestamp(&self, timestamp: u64) -> bool {
|
||||||
self.is_fork_active_at_timestamp(Hardfork::Shanghai, timestamp)
|
self.fork_timestamps
|
||||||
|
.shanghai
|
||||||
|
.map(|shanghai| timestamp >= shanghai)
|
||||||
|
.unwrap_or_else(|| self.is_fork_active_at_timestamp(Hardfork::Shanghai, timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`ForkFilter`](crate::ForkFilter) for the block described by [Head].
|
/// Creates a [`ForkFilter`](crate::ForkFilter) for the block described by [Head].
|
||||||
@ -325,11 +337,36 @@ impl From<EthersGenesis> for ChainSpec {
|
|||||||
chain: genesis.config.chain_id.into(),
|
chain: genesis.config.chain_id.into(),
|
||||||
genesis: genesis_block,
|
genesis: genesis_block,
|
||||||
genesis_hash: None,
|
genesis_hash: None,
|
||||||
|
fork_timestamps: ForkTimestamps::from_hardforks(&hardforks),
|
||||||
hardforks,
|
hardforks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Various timestamps of forks
|
||||||
|
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||||
|
pub struct ForkTimestamps {
|
||||||
|
/// The timestamp of the shanghai fork
|
||||||
|
pub shanghai: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ForkTimestamps {
|
||||||
|
/// Creates a new [`ForkTimestamps`] from the given hardforks by extracing 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);
|
||||||
|
}
|
||||||
|
timestamps
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the given shanghai timestamp
|
||||||
|
pub fn shanghai(mut self, shanghai: u64) -> Self {
|
||||||
|
self.shanghai = Some(shanghai);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A helper type for compatibility with geth's config
|
/// A helper type for compatibility with geth's config
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
@ -497,6 +534,7 @@ impl ChainSpecBuilder {
|
|||||||
chain: self.chain.expect("The chain is required"),
|
chain: self.chain.expect("The chain is required"),
|
||||||
genesis: self.genesis.expect("The genesis is required"),
|
genesis: self.genesis.expect("The genesis is required"),
|
||||||
genesis_hash: None,
|
genesis_hash: None,
|
||||||
|
fork_timestamps: ForkTimestamps::from_hardforks(&self.hardforks),
|
||||||
hardforks: self.hardforks,
|
hardforks: self.hardforks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -537,6 +575,11 @@ pub enum ForkCondition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ForkCondition {
|
impl ForkCondition {
|
||||||
|
/// Returns true if the fork condition is timestamp based.
|
||||||
|
pub fn is_timestamp(&self) -> bool {
|
||||||
|
matches!(self, ForkCondition::Timestamp(_))
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether the fork condition is satisfied at the given block.
|
/// Checks whether the fork condition is satisfied at the given block.
|
||||||
///
|
///
|
||||||
/// For TTD conditions, this will only return true if the activation block is already known.
|
/// For TTD conditions, this will only return true if the activation block is already known.
|
||||||
@ -622,6 +665,14 @@ impl ForkCondition {
|
|||||||
ForkCondition::Never => unreachable!(),
|
ForkCondition::Never => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the timestamp of the fork condition, if it is timestamp based.
|
||||||
|
pub fn as_timestamp(&self) -> Option<u64> {
|
||||||
|
match self {
|
||||||
|
ForkCondition::Timestamp(timestamp) => Some(*timestamp),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -644,6 +695,46 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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_activated_at_timestamp(1337));
|
||||||
|
assert!(!spec.is_shanghai_activated_at_timestamp(1336));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that all predefined timestamps are correctly set up in the chainspecs
|
||||||
|
#[test]
|
||||||
|
fn test_predefined_chain_spec_fork_timestamps() {
|
||||||
|
fn ensure_timestamp_fork_conditions(spec: &ChainSpec) {
|
||||||
|
// This is a sanity test that ensures we always set all currently known fork timestamps,
|
||||||
|
// this will fail if a new timestamp based fork condition has added to the hardforks but
|
||||||
|
// no corresponding entry in the ForkTimestamp types, See also
|
||||||
|
// [ForkTimestamps::from_hardforks]
|
||||||
|
|
||||||
|
// currently there are only 1 timestamps known: shanghai
|
||||||
|
let known_timestamp_based_forks = 1;
|
||||||
|
let num_timestamp_based_forks =
|
||||||
|
spec.hardforks.values().copied().filter(ForkCondition::is_timestamp).count();
|
||||||
|
assert_eq!(num_timestamp_based_forks, known_timestamp_based_forks);
|
||||||
|
|
||||||
|
// ensures all timestamp forks are set
|
||||||
|
assert!(spec.fork_timestamps.shanghai.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
for spec in [&*MAINNET, &*SEPOLIA] {
|
||||||
|
ensure_timestamp_fork_conditions(spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that we skip any fork blocks in block #0 (the genesis ruleset)
|
// Tests that we skip any fork blocks in block #0 (the genesis ruleset)
|
||||||
#[test]
|
#[test]
|
||||||
fn ignores_genesis_fork_blocks() {
|
fn ignores_genesis_fork_blocks() {
|
||||||
|
|||||||
@ -158,6 +158,7 @@ mod tests {
|
|||||||
genesis: Genesis::default(),
|
genesis: Genesis::default(),
|
||||||
genesis_hash: None,
|
genesis_hash: None,
|
||||||
hardforks: BTreeMap::from([(Hardfork::Frontier, ForkCondition::Never)]),
|
hardforks: BTreeMap::from([(Hardfork::Frontier, ForkCondition::Never)]),
|
||||||
|
fork_timestamps: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(Hardfork::Frontier.fork_id(&spec), None);
|
assert_eq!(Hardfork::Frontier.fork_id(&spec), None);
|
||||||
@ -170,6 +171,7 @@ mod tests {
|
|||||||
genesis: Genesis::default(),
|
genesis: Genesis::default(),
|
||||||
genesis_hash: None,
|
genesis_hash: None,
|
||||||
hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Never)]),
|
hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Never)]),
|
||||||
|
fork_timestamps: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(Hardfork::Shanghai.fork_filter(&spec), None);
|
assert_eq!(Hardfork::Shanghai.fork_filter(&spec), None);
|
||||||
|
|||||||
Reference in New Issue
Block a user