mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-08 22:14:57 -05:00
182 lines
5.1 KiB
Rust
182 lines
5.1 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::{ChainSpec, ForkCondition, ForkFilter, ForkId};
|
|
use std::{fmt::Display, str::FromStr};
|
|
|
|
/// The name of an Ethereum hardfork.
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
#[non_exhaustive]
|
|
pub enum Hardfork {
|
|
/// Frontier.
|
|
Frontier,
|
|
/// Homestead.
|
|
Homestead,
|
|
/// The DAO fork.
|
|
Dao,
|
|
/// Tangerine.
|
|
Tangerine,
|
|
/// Spurious Dragon.
|
|
SpuriousDragon,
|
|
/// Byzantium.
|
|
Byzantium,
|
|
/// Constantinople.
|
|
Constantinople,
|
|
/// Petersburg.
|
|
Petersburg,
|
|
/// Istanbul.
|
|
Istanbul,
|
|
/// Muir Glacier.
|
|
MuirGlacier,
|
|
/// Berlin.
|
|
Berlin,
|
|
/// London.
|
|
London,
|
|
/// Arrow Glacier.
|
|
ArrowGlacier,
|
|
/// Gray Glacier.
|
|
GrayGlacier,
|
|
/// Paris.
|
|
Paris,
|
|
/// Shanghai.
|
|
Shanghai,
|
|
}
|
|
|
|
impl Hardfork {
|
|
/// Get the [ForkId] for this hardfork in the given spec, if the fork is activated at any point.
|
|
pub fn fork_id(&self, spec: &ChainSpec) -> Option<ForkId> {
|
|
match spec.fork(*self) {
|
|
ForkCondition::Never => None,
|
|
_ => Some(spec.fork_id(&spec.fork(*self).satisfy())),
|
|
}
|
|
}
|
|
|
|
/// Get the [ForkFilter] for this hardfork in the given spec, if the fork is activated at any
|
|
/// point.
|
|
pub fn fork_filter(&self, spec: &ChainSpec) -> Option<ForkFilter> {
|
|
match spec.fork(*self) {
|
|
ForkCondition::Never => None,
|
|
_ => Some(spec.fork_filter(spec.fork(*self).satisfy())),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FromStr for Hardfork {
|
|
type Err = String;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let s = s.to_lowercase();
|
|
let hardfork = match s.as_str() {
|
|
"frontier" => Hardfork::Frontier,
|
|
"homestead" => Hardfork::Homestead,
|
|
"dao" => Hardfork::Dao,
|
|
"tangerine" => Hardfork::Tangerine,
|
|
"spuriousdragon" => Hardfork::SpuriousDragon,
|
|
"byzantium" => Hardfork::Byzantium,
|
|
"constantinople" => Hardfork::Constantinople,
|
|
"petersburg" => Hardfork::Petersburg,
|
|
"istanbul" => Hardfork::Istanbul,
|
|
"muirglacier" => Hardfork::MuirGlacier,
|
|
"berlin" => Hardfork::Berlin,
|
|
"london" => Hardfork::London,
|
|
"arrowglacier" => Hardfork::ArrowGlacier,
|
|
"grayglacier" => Hardfork::GrayGlacier,
|
|
"paris" => Hardfork::Paris,
|
|
"shanghai" => Hardfork::Shanghai,
|
|
_ => return Err(format!("Unknown hardfork: {s}")),
|
|
};
|
|
Ok(hardfork)
|
|
}
|
|
}
|
|
|
|
impl Display for Hardfork {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{self:?}")
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
use crate::{Chain, Genesis};
|
|
use std::collections::BTreeMap;
|
|
|
|
#[test]
|
|
fn check_hardfork_from_str() {
|
|
let hardfork_str = [
|
|
"frOntier",
|
|
"homEstead",
|
|
"dao",
|
|
"tAngerIne",
|
|
"spurIousdrAgon",
|
|
"byzAntium",
|
|
"constantinople",
|
|
"petersburg",
|
|
"istanbul",
|
|
"muirglacier",
|
|
"bErlin",
|
|
"lonDon",
|
|
"arrowglacier",
|
|
"grayglacier",
|
|
"PARIS",
|
|
"ShAnGhAI",
|
|
];
|
|
let expected_hardforks = [
|
|
Hardfork::Frontier,
|
|
Hardfork::Homestead,
|
|
Hardfork::Dao,
|
|
Hardfork::Tangerine,
|
|
Hardfork::SpuriousDragon,
|
|
Hardfork::Byzantium,
|
|
Hardfork::Constantinople,
|
|
Hardfork::Petersburg,
|
|
Hardfork::Istanbul,
|
|
Hardfork::MuirGlacier,
|
|
Hardfork::Berlin,
|
|
Hardfork::London,
|
|
Hardfork::ArrowGlacier,
|
|
Hardfork::GrayGlacier,
|
|
Hardfork::Paris,
|
|
Hardfork::Shanghai,
|
|
];
|
|
|
|
let hardforks: Vec<Hardfork> =
|
|
hardfork_str.iter().map(|h| Hardfork::from_str(h).unwrap()).collect();
|
|
|
|
assert_eq!(hardforks, expected_hardforks);
|
|
}
|
|
|
|
#[test]
|
|
fn check_nonexistent_hardfork_from_str() {
|
|
assert!(Hardfork::from_str("not a hardfork").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn check_fork_id_chainspec_with_fork_condition_never() {
|
|
let spec = ChainSpec {
|
|
chain: Chain::mainnet(),
|
|
genesis: Genesis::default(),
|
|
genesis_hash: None,
|
|
hardforks: BTreeMap::from([(Hardfork::Frontier, ForkCondition::Never)]),
|
|
fork_timestamps: Default::default(),
|
|
paris_block_and_final_difficulty: None,
|
|
};
|
|
|
|
assert_eq!(Hardfork::Frontier.fork_id(&spec), None);
|
|
}
|
|
|
|
#[test]
|
|
fn check_fork_filter_chainspec_with_fork_condition_never() {
|
|
let spec = ChainSpec {
|
|
chain: Chain::mainnet(),
|
|
genesis: Genesis::default(),
|
|
genesis_hash: None,
|
|
hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Never)]),
|
|
fork_timestamps: Default::default(),
|
|
paris_block_and_final_difficulty: None,
|
|
};
|
|
|
|
assert_eq!(Hardfork::Shanghai.fork_filter(&spec), None);
|
|
}
|
|
}
|