chore: op chainspec (#11415)

This commit is contained in:
greged93
2024-10-04 12:06:06 +02:00
committed by GitHub
parent c5cfaf116b
commit 72e0ab1000
6 changed files with 338 additions and 349 deletions

2
Cargo.lock generated
View File

@ -6508,13 +6508,11 @@ dependencies = [
"auto_impl",
"derive_more 1.0.0",
"once_cell",
"op-alloy-rpc-types",
"reth-ethereum-forks",
"reth-network-peers",
"reth-optimism-forks",
"reth-primitives-traits",
"reth-trie-common",
"serde",
"serde_json",
]

View File

@ -27,13 +27,9 @@ alloy-genesis.workspace = true
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
alloy-trie.workspace = true
# op
op-alloy-rpc-types = { workspace = true, optional = true }
# misc
auto_impl.workspace = true
once_cell.workspace = true
serde = { workspace = true, optional = true }
serde_json.workspace = true
derive_more.workspace = true
@ -44,12 +40,9 @@ alloy-eips = { workspace = true, features = ["arbitrary"] }
alloy-rlp = { workspace = true, features = ["arrayvec"] }
alloy-genesis.workspace = true
# op
op-alloy-rpc-types.workspace = true
[features]
default = ["std"]
optimism = ["serde", "dep:op-alloy-rpc-types", "reth-optimism-forks"]
optimism = ["reth-optimism-forks"]
std = [
"alloy-chains/std",
"alloy-eips/std",

View File

@ -590,56 +590,6 @@ impl ChainSpec {
impl From<Genesis> for ChainSpec {
fn from(genesis: Genesis) -> Self {
#[cfg(not(feature = "optimism"))]
{
into_ethereum_chain_spec(genesis)
}
#[cfg(feature = "optimism")]
{
into_optimism_chain_spec(genesis)
}
}
}
impl Hardforks for ChainSpec {
fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
self.hardforks.fork(fork)
}
fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
self.hardforks.forks_iter()
}
fn fork_id(&self, head: &Head) -> ForkId {
self.fork_id(head)
}
fn latest_fork_id(&self) -> ForkId {
self.latest_fork_id()
}
fn fork_filter(&self, head: Head) -> ForkFilter {
self.fork_filter(head)
}
}
impl EthereumHardforks for ChainSpec {
fn get_final_paris_total_difficulty(&self) -> Option<U256> {
self.get_final_paris_total_difficulty()
}
fn final_paris_total_difficulty(&self, block_number: u64) -> Option<U256> {
self.final_paris_total_difficulty(block_number)
}
}
#[cfg(feature = "optimism")]
impl reth_optimism_forks::OptimismHardforks for ChainSpec {}
/// Convert the given [`Genesis`] into an Ethereum [`ChainSpec`].
#[cfg(not(feature = "optimism"))]
fn into_ethereum_chain_spec(genesis: Genesis) -> ChainSpec {
// Block-based hardforks
let hardfork_opts = [
(EthereumHardfork::Homestead.boxed(), genesis.config.homestead_block),
@ -686,7 +636,9 @@ fn into_ethereum_chain_spec(genesis: Genesis) -> ChainSpec {
let mut time_hardforks = time_hardfork_opts
.into_iter()
.filter_map(|(hardfork, opt)| opt.map(|time| (hardfork, ForkCondition::Timestamp(time))))
.filter_map(|(hardfork, opt)| {
opt.map(|time| (hardfork, ForkCondition::Timestamp(time)))
})
.collect::<Vec<_>>();
hardforks.append(&mut time_hardforks);
@ -709,13 +661,11 @@ fn into_ethereum_chain_spec(genesis: Genesis) -> ChainSpec {
// have the deployment block in the genesis file, so we use block zero. We use the same
// deposit topic as the mainnet contract if we have the deposit contract address in the
// genesis json.
let deposit_contract = genesis.config.deposit_contract_address.map(|address| DepositContract {
address,
block: 0,
topic: MAINNET_DEPOSIT_CONTRACT.topic,
let deposit_contract = genesis.config.deposit_contract_address.map(|address| {
DepositContract { address, block: 0, topic: MAINNET_DEPOSIT_CONTRACT.topic }
});
ChainSpec {
Self {
chain: genesis.config.chain_id.into(),
genesis,
genesis_hash: OnceCell::new(),
@ -725,105 +675,42 @@ fn into_ethereum_chain_spec(genesis: Genesis) -> ChainSpec {
..Default::default()
}
}
}
impl Hardforks for ChainSpec {
fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
self.hardforks.fork(fork)
}
fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
self.hardforks.forks_iter()
}
fn fork_id(&self, head: &Head) -> ForkId {
self.fork_id(head)
}
fn latest_fork_id(&self) -> ForkId {
self.latest_fork_id()
}
fn fork_filter(&self, head: Head) -> ForkFilter {
self.fork_filter(head)
}
}
impl EthereumHardforks for ChainSpec {
fn get_final_paris_total_difficulty(&self) -> Option<U256> {
self.get_final_paris_total_difficulty()
}
fn final_paris_total_difficulty(&self, block_number: u64) -> Option<U256> {
self.final_paris_total_difficulty(block_number)
}
}
#[cfg(feature = "optimism")]
/// Convert the given [`Genesis`] into an Optimism [`ChainSpec`].
fn into_optimism_chain_spec(genesis: Genesis) -> ChainSpec {
use reth_optimism_forks::OptimismHardfork;
let optimism_genesis_info = OptimismGenesisInfo::extract_from(&genesis);
let genesis_info = optimism_genesis_info.optimism_chain_info.genesis_info.unwrap_or_default();
// Block-based hardforks
let hardfork_opts = [
(EthereumHardfork::Homestead.boxed(), genesis.config.homestead_block),
(EthereumHardfork::Tangerine.boxed(), genesis.config.eip150_block),
(EthereumHardfork::SpuriousDragon.boxed(), genesis.config.eip155_block),
(EthereumHardfork::Byzantium.boxed(), genesis.config.byzantium_block),
(EthereumHardfork::Constantinople.boxed(), genesis.config.constantinople_block),
(EthereumHardfork::Petersburg.boxed(), genesis.config.petersburg_block),
(EthereumHardfork::Istanbul.boxed(), genesis.config.istanbul_block),
(EthereumHardfork::MuirGlacier.boxed(), genesis.config.muir_glacier_block),
(EthereumHardfork::Berlin.boxed(), genesis.config.berlin_block),
(EthereumHardfork::London.boxed(), genesis.config.london_block),
(EthereumHardfork::ArrowGlacier.boxed(), genesis.config.arrow_glacier_block),
(EthereumHardfork::GrayGlacier.boxed(), genesis.config.gray_glacier_block),
(OptimismHardfork::Bedrock.boxed(), genesis_info.bedrock_block),
];
let mut block_hardforks = hardfork_opts
.into_iter()
.filter_map(|(hardfork, opt)| opt.map(|block| (hardfork, ForkCondition::Block(block))))
.collect::<Vec<_>>();
// Paris
let paris_block_and_final_difficulty =
if let Some(ttd) = genesis.config.terminal_total_difficulty {
block_hardforks.push((
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD {
total_difficulty: ttd,
fork_block: genesis.config.merge_netsplit_block,
},
));
genesis.config.merge_netsplit_block.map(|block| (block, ttd))
} else {
None
};
// Time-based hardforks
let time_hardfork_opts = [
(EthereumHardfork::Shanghai.boxed(), genesis.config.shanghai_time),
(EthereumHardfork::Cancun.boxed(), genesis.config.cancun_time),
(EthereumHardfork::Prague.boxed(), genesis.config.prague_time),
(OptimismHardfork::Regolith.boxed(), genesis_info.regolith_time),
(OptimismHardfork::Canyon.boxed(), genesis_info.canyon_time),
(OptimismHardfork::Ecotone.boxed(), genesis_info.ecotone_time),
(OptimismHardfork::Fjord.boxed(), genesis_info.fjord_time),
(OptimismHardfork::Granite.boxed(), genesis_info.granite_time),
];
let mut time_hardforks = time_hardfork_opts
.into_iter()
.filter_map(|(hardfork, opt)| opt.map(|time| (hardfork, ForkCondition::Timestamp(time))))
.collect::<Vec<_>>();
block_hardforks.append(&mut time_hardforks);
// Ordered Hardforks
let mainnet_hardforks = OptimismHardfork::op_mainnet();
let mainnet_order = mainnet_hardforks.forks_iter();
let mut ordered_hardforks = Vec::with_capacity(block_hardforks.len());
for (hardfork, _) in mainnet_order {
if let Some(pos) = block_hardforks.iter().position(|(e, _)| **e == *hardfork) {
ordered_hardforks.push(block_hardforks.remove(pos));
}
}
// append the remaining unknown hardforks to ensure we don't filter any out
ordered_hardforks.append(&mut block_hardforks);
// NOTE: in full node, we prune all receipts except the deposit contract's. We do not
// have the deployment block in the genesis file, so we use block zero. We use the same
// deposit topic as the mainnet contract if we have the deposit contract address in the
// genesis json.
let deposit_contract = genesis.config.deposit_contract_address.map(|address| DepositContract {
address,
block: 0,
topic: MAINNET_DEPOSIT_CONTRACT.topic,
});
ChainSpec {
chain: genesis.config.chain_id.into(),
genesis,
genesis_hash: OnceCell::new(),
hardforks: ChainHardforks::new(ordered_hardforks),
paris_block_and_final_difficulty,
deposit_contract,
base_fee_params: optimism_genesis_info.base_fee_params,
..Default::default()
}
}
impl reth_optimism_forks::OptimismHardforks for ChainSpec {}
/// A trait for reading the current chainspec.
#[auto_impl::auto_impl(&, Arc)]
@ -1102,59 +989,6 @@ impl DepositContract {
}
}
/// Genesis info for Optimism.
#[cfg(feature = "optimism")]
#[derive(Default, Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct OptimismGenesisInfo {
optimism_chain_info: op_alloy_rpc_types::genesis::OptimismChainInfo,
#[serde(skip)]
base_fee_params: BaseFeeParamsKind,
}
#[cfg(feature = "optimism")]
impl OptimismGenesisInfo {
fn extract_from(genesis: &Genesis) -> Self {
let mut info = Self {
optimism_chain_info: op_alloy_rpc_types::genesis::OptimismChainInfo::extract_from(
&genesis.config.extra_fields,
)
.unwrap_or_default(),
..Default::default()
};
if let Some(optimism_base_fee_info) = &info.optimism_chain_info.base_fee_info {
if let (Some(elasticity), Some(denominator)) = (
optimism_base_fee_info.eip1559_elasticity,
optimism_base_fee_info.eip1559_denominator,
) {
let base_fee_params = if let Some(canyon_denominator) =
optimism_base_fee_info.eip1559_denominator_canyon
{
BaseFeeParamsKind::Variable(
vec![
(
EthereumHardfork::London.boxed(),
BaseFeeParams::new(denominator as u128, elasticity as u128),
),
(
reth_optimism_forks::OptimismHardfork::Canyon.boxed(),
BaseFeeParams::new(canyon_denominator as u128, elasticity as u128),
),
]
.into(),
)
} else {
BaseFeeParams::new(denominator as u128, elasticity as u128).into()
};
info.base_fee_params = base_fee_params;
}
}
info
}
}
/// Verifies [`ChainSpec`] configuration against expected data in given cases.
#[cfg(any(test, feature = "test-utils"))]
pub fn test_fork_ids(spec: &ChainSpec, cases: &[(Head, ForkId)]) {
@ -2477,7 +2311,6 @@ Post-merge hard forks (timestamp based):
}
#[test]
#[cfg(not(feature = "optimism"))]
fn test_fork_order_ethereum_mainnet() {
let genesis = Genesis {
config: ChainConfig {
@ -2506,7 +2339,7 @@ Post-merge hard forks (timestamp based):
..Default::default()
};
let chain_spec = into_ethereum_chain_spec(genesis);
let chain_spec: ChainSpec = genesis.into();
let hardforks: Vec<_> = chain_spec.hardforks.forks_iter().map(|(h, _)| h).collect();
let expected_hardforks = vec![
@ -2534,80 +2367,4 @@ Post-merge hard forks (timestamp based):
.all(|(expected, actual)| &**expected == *actual));
assert_eq!(expected_hardforks.len(), hardforks.len());
}
#[test]
#[cfg(feature = "optimism")]
fn test_fork_order_optimism_mainnet() {
use reth_optimism_forks::OptimismHardfork;
let genesis = Genesis {
config: ChainConfig {
chain_id: 0,
homestead_block: Some(0),
dao_fork_block: Some(0),
dao_fork_support: false,
eip150_block: Some(0),
eip155_block: Some(0),
eip158_block: Some(0),
byzantium_block: Some(0),
constantinople_block: Some(0),
petersburg_block: Some(0),
istanbul_block: Some(0),
muir_glacier_block: Some(0),
berlin_block: Some(0),
london_block: Some(0),
arrow_glacier_block: Some(0),
gray_glacier_block: Some(0),
merge_netsplit_block: Some(0),
shanghai_time: Some(0),
cancun_time: Some(0),
terminal_total_difficulty: Some(U256::ZERO),
extra_fields: [
(String::from("bedrockBlock"), 0.into()),
(String::from("regolithTime"), 0.into()),
(String::from("canyonTime"), 0.into()),
(String::from("ecotoneTime"), 0.into()),
(String::from("fjordTime"), 0.into()),
(String::from("graniteTime"), 0.into()),
]
.into_iter()
.collect(),
..Default::default()
},
..Default::default()
};
let chain_spec: ChainSpec = into_optimism_chain_spec(genesis);
let hardforks: Vec<_> = chain_spec.hardforks.forks_iter().map(|(h, _)| h).collect();
let expected_hardforks = vec![
EthereumHardfork::Homestead.boxed(),
EthereumHardfork::Tangerine.boxed(),
EthereumHardfork::SpuriousDragon.boxed(),
EthereumHardfork::Byzantium.boxed(),
EthereumHardfork::Constantinople.boxed(),
EthereumHardfork::Petersburg.boxed(),
EthereumHardfork::Istanbul.boxed(),
EthereumHardfork::MuirGlacier.boxed(),
EthereumHardfork::Berlin.boxed(),
EthereumHardfork::London.boxed(),
EthereumHardfork::ArrowGlacier.boxed(),
EthereumHardfork::GrayGlacier.boxed(),
EthereumHardfork::Paris.boxed(),
OptimismHardfork::Bedrock.boxed(),
OptimismHardfork::Regolith.boxed(),
EthereumHardfork::Shanghai.boxed(),
OptimismHardfork::Canyon.boxed(),
EthereumHardfork::Cancun.boxed(),
OptimismHardfork::Ecotone.boxed(),
OptimismHardfork::Fjord.boxed(),
OptimismHardfork::Granite.boxed(),
];
assert!(expected_hardforks
.iter()
.zip(hardforks.iter())
.all(|(expected, actual)| &**expected == *actual));
assert_eq!(expected_hardforks.len(), hardforks.len());
}
}

View File

@ -26,12 +26,15 @@ alloy-chains.workspace = true
alloy-genesis.workspace = true
alloy-primitives.workspace = true
# op
op-alloy-rpc-types.workspace = true
# io
serde_json.workspace = true
# misc
once_cell.workspace = true
derive_more.workspace = true
once_cell.workspace = true
[dev-dependencies]
reth-chainspec = { workspace = true, features = ["test-utils"] }

View File

@ -1,5 +1,8 @@
//! OP stack variation of chain spec constants.
use alloy_primitives::{address, b256};
use reth_chainspec::DepositContract;
//------------------------------- BASE MAINNET -------------------------------//
/// Max gas limit on Base: <https://basescan.org/block/17208876>
@ -9,3 +12,10 @@ pub const BASE_MAINNET_MAX_GAS_LIMIT: u64 = 105_000_000;
/// Max gas limit on Base Sepolia: <https://sepolia.basescan.org/block/12506483>
pub const BASE_SEPOLIA_MAX_GAS_LIMIT: u64 = 45_000_000;
/// Deposit contract address: `0x00000000219ab540356cbb839cbe05303d7705fa`
pub(crate) const MAINNET_DEPOSIT_CONTRACT: DepositContract = DepositContract::new(
address!("00000000219ab540356cbb839cbe05303d7705fa"),
11052984,
b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"),
);

View File

@ -26,11 +26,14 @@ pub use dev::OP_DEV;
pub use op::OP_MAINNET;
pub use op_sepolia::OP_SEPOLIA;
use crate::constants::MAINNET_DEPOSIT_CONTRACT;
use derive_more::{Constructor, Deref, Into};
use once_cell::sync::OnceCell;
use reth_chainspec::{
BaseFeeParams, ChainSpec, DepositContract, EthChainSpec, EthereumHardforks, ForkFilter, ForkId,
Hardforks, Head,
BaseFeeParams, BaseFeeParamsKind, ChainSpec, DepositContract, EthChainSpec, EthereumHardforks,
ForkFilter, ForkId, Hardforks, Head,
};
use reth_ethereum_forks::{ChainHardforks, EthereumHardfork, ForkCondition};
use reth_network_peers::NodeRecord;
use reth_primitives_traits::Header;
@ -52,14 +55,14 @@ impl EthChainSpec for OpChainSpec {
self.inner.chain()
}
fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams {
self.inner.base_fee_params_at_timestamp(timestamp)
}
fn base_fee_params_at_block(&self, block_number: u64) -> BaseFeeParams {
self.inner.base_fee_params_at_block(block_number)
}
fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams {
self.inner.base_fee_params_at_timestamp(timestamp)
}
fn deposit_contract(&self) -> Option<&DepositContract> {
self.inner.deposit_contract()
}
@ -118,20 +121,170 @@ impl Hardforks for OpChainSpec {
}
impl EthereumHardforks for OpChainSpec {
fn get_final_paris_total_difficulty(&self) -> Option<U256> {
self.inner.get_final_paris_total_difficulty()
}
fn final_paris_total_difficulty(&self, block_number: u64) -> Option<U256> {
self.inner.final_paris_total_difficulty(block_number)
}
}
fn get_final_paris_total_difficulty(&self) -> Option<U256> {
self.inner.get_final_paris_total_difficulty()
impl From<Genesis> for OpChainSpec {
fn from(genesis: Genesis) -> Self {
use reth_optimism_forks::OptimismHardfork;
let optimism_genesis_info = OptimismGenesisInfo::extract_from(&genesis);
let genesis_info =
optimism_genesis_info.optimism_chain_info.genesis_info.unwrap_or_default();
// Block-based hardforks
let hardfork_opts = [
(EthereumHardfork::Homestead.boxed(), genesis.config.homestead_block),
(EthereumHardfork::Tangerine.boxed(), genesis.config.eip150_block),
(EthereumHardfork::SpuriousDragon.boxed(), genesis.config.eip155_block),
(EthereumHardfork::Byzantium.boxed(), genesis.config.byzantium_block),
(EthereumHardfork::Constantinople.boxed(), genesis.config.constantinople_block),
(EthereumHardfork::Petersburg.boxed(), genesis.config.petersburg_block),
(EthereumHardfork::Istanbul.boxed(), genesis.config.istanbul_block),
(EthereumHardfork::MuirGlacier.boxed(), genesis.config.muir_glacier_block),
(EthereumHardfork::Berlin.boxed(), genesis.config.berlin_block),
(EthereumHardfork::London.boxed(), genesis.config.london_block),
(EthereumHardfork::ArrowGlacier.boxed(), genesis.config.arrow_glacier_block),
(EthereumHardfork::GrayGlacier.boxed(), genesis.config.gray_glacier_block),
(OptimismHardfork::Bedrock.boxed(), genesis_info.bedrock_block),
];
let mut block_hardforks = hardfork_opts
.into_iter()
.filter_map(|(hardfork, opt)| opt.map(|block| (hardfork, ForkCondition::Block(block))))
.collect::<Vec<_>>();
// Paris
let paris_block_and_final_difficulty =
if let Some(ttd) = genesis.config.terminal_total_difficulty {
block_hardforks.push((
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD {
total_difficulty: ttd,
fork_block: genesis.config.merge_netsplit_block,
},
));
genesis.config.merge_netsplit_block.map(|block| (block, ttd))
} else {
None
};
// Time-based hardforks
let time_hardfork_opts = [
(EthereumHardfork::Shanghai.boxed(), genesis.config.shanghai_time),
(EthereumHardfork::Cancun.boxed(), genesis.config.cancun_time),
(EthereumHardfork::Prague.boxed(), genesis.config.prague_time),
(OptimismHardfork::Regolith.boxed(), genesis_info.regolith_time),
(OptimismHardfork::Canyon.boxed(), genesis_info.canyon_time),
(OptimismHardfork::Ecotone.boxed(), genesis_info.ecotone_time),
(OptimismHardfork::Fjord.boxed(), genesis_info.fjord_time),
(OptimismHardfork::Granite.boxed(), genesis_info.granite_time),
];
let mut time_hardforks = time_hardfork_opts
.into_iter()
.filter_map(|(hardfork, opt)| {
opt.map(|time| (hardfork, ForkCondition::Timestamp(time)))
})
.collect::<Vec<_>>();
block_hardforks.append(&mut time_hardforks);
// Ordered Hardforks
let mainnet_hardforks = OptimismHardfork::op_mainnet();
let mainnet_order = mainnet_hardforks.forks_iter();
let mut ordered_hardforks = Vec::with_capacity(block_hardforks.len());
for (hardfork, _) in mainnet_order {
if let Some(pos) = block_hardforks.iter().position(|(e, _)| **e == *hardfork) {
ordered_hardforks.push(block_hardforks.remove(pos));
}
}
// append the remaining unknown hardforks to ensure we don't filter any out
ordered_hardforks.append(&mut block_hardforks);
// NOTE: in full node, we prune all receipts except the deposit contract's. We do not
// have the deployment block in the genesis file, so we use block zero. We use the same
// deposit topic as the mainnet contract if we have the deposit contract address in the
// genesis json.
let deposit_contract = genesis.config.deposit_contract_address.map(|address| {
DepositContract { address, block: 0, topic: MAINNET_DEPOSIT_CONTRACT.topic }
});
Self {
inner: ChainSpec {
chain: genesis.config.chain_id.into(),
genesis,
genesis_hash: OnceCell::new(),
hardforks: ChainHardforks::new(ordered_hardforks),
paris_block_and_final_difficulty,
deposit_contract,
base_fee_params: optimism_genesis_info.base_fee_params,
..Default::default()
},
}
}
}
#[derive(Default, Debug)]
struct OptimismGenesisInfo {
optimism_chain_info: op_alloy_rpc_types::genesis::OptimismChainInfo,
base_fee_params: BaseFeeParamsKind,
}
impl OptimismGenesisInfo {
fn extract_from(genesis: &Genesis) -> Self {
let mut info = Self {
optimism_chain_info: op_alloy_rpc_types::genesis::OptimismChainInfo::extract_from(
&genesis.config.extra_fields,
)
.unwrap_or_default(),
..Default::default()
};
if let Some(optimism_base_fee_info) = &info.optimism_chain_info.base_fee_info {
if let (Some(elasticity), Some(denominator)) = (
optimism_base_fee_info.eip1559_elasticity,
optimism_base_fee_info.eip1559_denominator,
) {
let base_fee_params = if let Some(canyon_denominator) =
optimism_base_fee_info.eip1559_denominator_canyon
{
BaseFeeParamsKind::Variable(
vec![
(
EthereumHardfork::London.boxed(),
BaseFeeParams::new(denominator as u128, elasticity as u128),
),
(
reth_optimism_forks::OptimismHardfork::Canyon.boxed(),
BaseFeeParams::new(canyon_denominator as u128, elasticity as u128),
),
]
.into(),
)
} else {
BaseFeeParams::new(denominator as u128, elasticity as u128).into()
};
info.base_fee_params = base_fee_params;
}
}
info
}
}
#[cfg(test)]
mod tests {
use alloy_genesis::Genesis;
use alloy_genesis::{ChainConfig, Genesis};
use alloy_primitives::b256;
use reth_chainspec::{test_fork_ids, BaseFeeParams, BaseFeeParamsKind, ChainSpec};
use reth_chainspec::{test_fork_ids, BaseFeeParams, BaseFeeParamsKind};
use reth_ethereum_forks::{EthereumHardfork, ForkCondition, ForkHash, ForkId, Head};
use reth_optimism_forks::{OptimismHardfork, OptimismHardforks};
@ -383,7 +536,7 @@ mod tests {
})
);
let chain_spec: ChainSpec = genesis.into();
let chain_spec: OpChainSpec = genesis.into();
assert_eq!(
chain_spec.base_fee_params,
@ -449,7 +602,7 @@ mod tests {
})
);
let chain_spec: ChainSpec = genesis.into();
let chain_spec: OpChainSpec = genesis.into();
assert_eq!(
chain_spec.base_fee_params,
@ -511,7 +664,7 @@ mod tests {
}
"#;
let genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
let chainspec = ChainSpec::from(genesis.clone());
let chainspec = OpChainSpec::from(genesis.clone());
let actual_chain_id = genesis.config.chain_id;
assert_eq!(actual_chain_id, 8453);
@ -552,4 +705,79 @@ mod tests {
assert!(chainspec.is_fork_active_at_timestamp(OptimismHardfork::Regolith, 20));
}
#[test]
fn test_fork_order_optimism_mainnet() {
use reth_optimism_forks::OptimismHardfork;
let genesis = Genesis {
config: ChainConfig {
chain_id: 0,
homestead_block: Some(0),
dao_fork_block: Some(0),
dao_fork_support: false,
eip150_block: Some(0),
eip155_block: Some(0),
eip158_block: Some(0),
byzantium_block: Some(0),
constantinople_block: Some(0),
petersburg_block: Some(0),
istanbul_block: Some(0),
muir_glacier_block: Some(0),
berlin_block: Some(0),
london_block: Some(0),
arrow_glacier_block: Some(0),
gray_glacier_block: Some(0),
merge_netsplit_block: Some(0),
shanghai_time: Some(0),
cancun_time: Some(0),
terminal_total_difficulty: Some(U256::ZERO),
extra_fields: [
(String::from("bedrockBlock"), 0.into()),
(String::from("regolithTime"), 0.into()),
(String::from("canyonTime"), 0.into()),
(String::from("ecotoneTime"), 0.into()),
(String::from("fjordTime"), 0.into()),
(String::from("graniteTime"), 0.into()),
]
.into_iter()
.collect(),
..Default::default()
},
..Default::default()
};
let chain_spec: OpChainSpec = genesis.into();
let hardforks: Vec<_> = chain_spec.hardforks.forks_iter().map(|(h, _)| h).collect();
let expected_hardforks = vec![
EthereumHardfork::Homestead.boxed(),
EthereumHardfork::Tangerine.boxed(),
EthereumHardfork::SpuriousDragon.boxed(),
EthereumHardfork::Byzantium.boxed(),
EthereumHardfork::Constantinople.boxed(),
EthereumHardfork::Petersburg.boxed(),
EthereumHardfork::Istanbul.boxed(),
EthereumHardfork::MuirGlacier.boxed(),
EthereumHardfork::Berlin.boxed(),
EthereumHardfork::London.boxed(),
EthereumHardfork::ArrowGlacier.boxed(),
EthereumHardfork::GrayGlacier.boxed(),
EthereumHardfork::Paris.boxed(),
OptimismHardfork::Bedrock.boxed(),
OptimismHardfork::Regolith.boxed(),
EthereumHardfork::Shanghai.boxed(),
OptimismHardfork::Canyon.boxed(),
EthereumHardfork::Cancun.boxed(),
OptimismHardfork::Ecotone.boxed(),
OptimismHardfork::Fjord.boxed(),
OptimismHardfork::Granite.boxed(),
];
assert!(expected_hardforks
.iter()
.zip(hardforks.iter())
.all(|(expected, actual)| &**expected == *actual));
assert_eq!(expected_hardforks.len(), hardforks.len());
}
}