add ChainConfig utils for block and timestamp comparisons (#5978)

Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
This commit is contained in:
Thomas Coratger
2024-01-09 18:15:20 +01:00
committed by GitHub
parent d421120a25
commit 75608610a5

View File

@ -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)
@ -208,55 +214,55 @@ 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>,
@ -264,11 +270,11 @@ pub struct ChainConfig {
#[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>,
@ -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 {