Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ChainConfig utils for block and timestamp comparisons #5978

Merged
merged 5 commits into from
Jan 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 113 additions & 16 deletions crates/primitives/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,13 @@ impl From<GenesisAccount> for Account {
}
}

/// Represents a node's chain configuration.
/// Defines core blockchain settings per block.
///
/// Tailors unique settings for each network based on its genesis block.
///
/// Governs crucial blockchain behavior and adaptability.
///
/// Encapsulates parameters shaping network evolution and behavior.
///
/// See [geth's `ChainConfig`
/// struct](https://github.com/ethereum/go-ethereum/blob/64dccf7aa411c5c7cd36090c3d9b9892945ae813/params/config.go#L349)
Expand All @@ -208,67 +214,67 @@ pub struct ChainConfig {
/// Whether or not the node supports the DAO hard-fork.
pub dao_fork_support: bool,

/// The EIP-150 hard fork block (None = no fork).
/// The [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) hard fork block (None = no fork).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub eip150_block: Option<u64>,

/// The EIP-150 hard fork hash.
/// The [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) hard fork hash.
#[serde(skip_serializing_if = "Option::is_none")]
pub eip150_hash: Option<B256>,

/// The EIP-155 hard fork block.
/// The [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) hard fork block.
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub eip155_block: Option<u64>,

/// The EIP-158 hard fork block.
/// The [EIP-158](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-158.md) hard fork block.
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub eip158_block: Option<u64>,

/// The Byzantium hard fork block.
/// The Byzantium hard fork block (None = no fork, 0 = already on byzantium).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub byzantium_block: Option<u64>,

/// The Constantinople hard fork block.
/// The Constantinople hard fork block (None = no fork, 0 = already on constantinople).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub constantinople_block: Option<u64>,

/// The Petersburg hard fork block.
/// The Petersburg hard fork block (None = no fork, 0 = already on petersburg).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub petersburg_block: Option<u64>,

/// The Istanbul hard fork block.
/// The Istanbul hard fork block (None = no fork, 0 = already on istanbul).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub istanbul_block: Option<u64>,

/// The Muir Glacier hard fork block.
/// The Muir Glacier hard fork block (None = no fork, 0 = already on muir glacier).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub muir_glacier_block: Option<u64>,

/// The Berlin hard fork block.
/// The Berlin hard fork block (None = no fork, 0 = already on berlin).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub berlin_block: Option<u64>,

/// The London hard fork block.
/// The London hard fork block (None = no fork, 0 = already on london).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub london_block: Option<u64>,

/// The Arrow Glacier hard fork block.
/// The Arrow Glacier hard fork block (None = no fork, 0 = already on arrow glacier).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub arrow_glacier_block: Option<u64>,

/// The Gray Glacier hard fork block.
/// The Gray Glacier hard fork block (None = no fork, 0 = already on gray glacier).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub gray_glacier_block: Option<u64>,

/// Virtual fork after the merge to use as a network splitter.
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub merge_netsplit_block: Option<u64>,

/// Shanghai switch time.
/// Shanghai switch time (None = no fork, 0 = already on shanghai).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub shanghai_time: Option<u64>,

/// Cancun switch time.
/// Cancun switch time (None = no fork, 0 = already on cancun).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
pub cancun_time: Option<u64>,

Expand All @@ -292,6 +298,97 @@ pub struct ChainConfig {
pub clique: Option<CliqueConfig>,
}

impl ChainConfig {
/// Checks if the blockchain is active at or after the Homestead fork block.
pub fn is_homestead_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.homestead_block, block)
}

/// Checks if the blockchain is active at or after the EIP150 fork block.
pub fn is_eip150_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.eip150_block, block)
}

/// Checks if the blockchain is active at or after the EIP155 fork block.
pub fn is_eip155_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.eip155_block, block)
}

/// Checks if the blockchain is active at or after the EIP158 fork block.
pub fn is_eip158_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.eip158_block, block)
}

/// Checks if the blockchain is active at or after the Byzantium fork block.
pub fn is_byzantium_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.byzantium_block, block)
}

/// Checks if the blockchain is active at or after the Constantinople fork block.
pub fn is_constantinople_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.constantinople_block, block)
}

/// Checks if the blockchain is active at or after the Muir Glacier (EIP-2384) fork block.
pub fn is_muir_glacier_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.muir_glacier_block, block)
}

/// Checks if the blockchain is active at or after the Petersburg fork block.
pub fn is_petersburg_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.petersburg_block, block)
}

/// Checks if the blockchain is active at or after the Istanbul fork block.
pub fn is_istanbul_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.istanbul_block, block)
}

/// Checks if the blockchain is active at or after the Berlin fork block.
pub fn is_berlin_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.berlin_block, block)
}

/// Checks if the blockchain is active at or after the London fork block.
pub fn is_london_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.london_block, block)
}

/// Checks if the blockchain is active at or after the Arrow Glacier (EIP-4345) fork block.
pub fn is_arrow_glacier_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.arrow_glacier_block, block)
}

/// Checks if the blockchain is active at or after the Gray Glacier (EIP-5133) fork block.
pub fn is_gray_glacier_active_at_block(&self, block: u64) -> bool {
self.is_active_at_block(self.gray_glacier_block, block)
}

/// Checks if the blockchain is active at or after the Shanghai fork block and the specified
/// timestamp.
pub fn is_shanghai_active_at_block_and_timestamp(&self, block: u64, timestamp: u64) -> bool {
self.is_london_active_at_block(block) &&
self.is_active_at_timestamp(self.shanghai_time, timestamp)
}

/// Checks if the blockchain is active at or after the Cancun fork block and the specified
/// timestamp.
pub fn is_cancun_active_at_block_and_timestamp(&self, block: u64, timestamp: u64) -> bool {
self.is_london_active_at_block(block) &&
self.is_active_at_timestamp(self.cancun_time, timestamp)
}

// Private function handling the comparison logic for block numbers
fn is_active_at_block(&self, config_block: Option<u64>, block: u64) -> bool {
config_block.map_or(false, |cb| cb <= block)
}

// Private function handling the comparison logic for timestamps
fn is_active_at_timestamp(&self, config_timestamp: Option<u64>, timestamp: u64) -> bool {
config_timestamp.map_or(false, |cb| cb <= timestamp)
}
}

// used only for serde
#[inline]
const fn mainnet_id() -> u64 {
Expand Down
Loading