diff --git a/Cargo.lock b/Cargo.lock index 65e8b864a..a24097587 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6498,6 +6498,29 @@ dependencies = [ "thiserror", ] +[[package]] +name = "reth-chainspec" +version = "1.0.0-rc.1" +dependencies = [ + "alloy-chains", + "alloy-eips 0.1.0", + "alloy-genesis", + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "derive_more", + "nybbles", + "once_cell", + "rand 0.8.5", + "reth-ethereum-forks", + "reth-network-peers", + "reth-primitives-traits", + "reth-rpc-types", + "reth-trie-common", + "serde", + "serde_json", +] + [[package]] name = "reth-cli-runner" version = "1.0.0-rc.1" @@ -7660,7 +7683,6 @@ dependencies = [ name = "reth-primitives" version = "1.0.0-rc.1" dependencies = [ - "alloy-chains", "alloy-consensus 0.1.0", "alloy-eips 0.1.0", "alloy-genesis", @@ -7683,9 +7705,9 @@ dependencies = [ "proptest-derive", "rand 0.8.5", "rayon", + "reth-chainspec", "reth-codecs", "reth-ethereum-forks", - "reth-network-peers", "reth-primitives-traits", "reth-static-file-types", "reth-trie-common", diff --git a/Cargo.toml b/Cargo.toml index b0f2e2048..63d297ab8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ members = [ "bin/reth/", "crates/blockchain-tree/", "crates/blockchain-tree-api/", + "crates/chainspec/", "crates/cli/runner/", "crates/config/", "crates/consensus/auto-seal/", @@ -246,6 +247,7 @@ reth-basic-payload-builder = { path = "crates/payload/basic" } reth-beacon-consensus = { path = "crates/consensus/beacon" } reth-blockchain-tree = { path = "crates/blockchain-tree" } reth-blockchain-tree-api = { path = "crates/blockchain-tree-api" } +reth-chainspec = { path = "crates/chainspec" } reth-cli-runner = { path = "crates/cli/runner" } reth-codecs = { path = "crates/storage/codecs" } reth-codecs-derive = { path = "crates/storage/codecs/derive" } diff --git a/crates/chainspec/Cargo.toml b/crates/chainspec/Cargo.toml new file mode 100644 index 000000000..8c1d4d4da --- /dev/null +++ b/crates/chainspec/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "reth-chainspec" +version.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[lints] +workspace = true + +[dependencies] +# reth +reth-ethereum-forks.workspace = true +reth-network-peers.workspace = true +reth-trie-common.workspace = true +reth-primitives-traits.workspace = true + +# ethereum +alloy-chains = { workspace = true, features = ["serde", "rlp"] } +alloy-eips = { workspace = true, features = ["serde"] } +alloy-genesis.workspace = true +alloy-primitives = { workspace = true, features = ["rand", "rlp"] } +alloy-trie.workspace = true + +# misc +once_cell.workspace = true +serde.workspace = true +serde_json.workspace = true +derive_more.workspace = true + +[dev-dependencies] +# eth +nybbles = { workspace = true, features = ["arbitrary"] } +alloy-trie = { workspace = true, features = ["arbitrary"] } +alloy-eips = { workspace = true, features = ["arbitrary"] } +alloy-rlp = { workspace = true, features = ["arrayvec"] } +alloy-genesis.workspace = true +reth-rpc-types.workspace = true +rand.workspace = true + +[features] +default = ["std"] +optimism = [ + "reth-ethereum-forks/optimism" +] +std = [] +arbitrary = [ + "alloy-chains/arbitrary" +] + + diff --git a/crates/primitives/res/genesis/base.json b/crates/chainspec/res/genesis/base.json similarity index 100% rename from crates/primitives/res/genesis/base.json rename to crates/chainspec/res/genesis/base.json diff --git a/crates/primitives/res/genesis/dev.json b/crates/chainspec/res/genesis/dev.json similarity index 100% rename from crates/primitives/res/genesis/dev.json rename to crates/chainspec/res/genesis/dev.json diff --git a/crates/primitives/res/genesis/goerli.json b/crates/chainspec/res/genesis/goerli.json similarity index 100% rename from crates/primitives/res/genesis/goerli.json rename to crates/chainspec/res/genesis/goerli.json diff --git a/crates/primitives/res/genesis/holesky.json b/crates/chainspec/res/genesis/holesky.json similarity index 100% rename from crates/primitives/res/genesis/holesky.json rename to crates/chainspec/res/genesis/holesky.json diff --git a/crates/primitives/res/genesis/mainnet.json b/crates/chainspec/res/genesis/mainnet.json similarity index 100% rename from crates/primitives/res/genesis/mainnet.json rename to crates/chainspec/res/genesis/mainnet.json diff --git a/crates/primitives/res/genesis/optimism.json b/crates/chainspec/res/genesis/optimism.json similarity index 100% rename from crates/primitives/res/genesis/optimism.json rename to crates/chainspec/res/genesis/optimism.json diff --git a/crates/primitives/res/genesis/sepolia.json b/crates/chainspec/res/genesis/sepolia.json similarity index 100% rename from crates/primitives/res/genesis/sepolia.json rename to crates/chainspec/res/genesis/sepolia.json diff --git a/crates/primitives/res/genesis/sepolia_base.json b/crates/chainspec/res/genesis/sepolia_base.json similarity index 100% rename from crates/primitives/res/genesis/sepolia_base.json rename to crates/chainspec/res/genesis/sepolia_base.json diff --git a/crates/primitives/res/genesis/sepolia_op.json b/crates/chainspec/res/genesis/sepolia_op.json similarity index 100% rename from crates/primitives/res/genesis/sepolia_op.json rename to crates/chainspec/res/genesis/sepolia_op.json diff --git a/crates/chainspec/src/constants/mod.rs b/crates/chainspec/src/constants/mod.rs new file mode 100644 index 000000000..9af4f946b --- /dev/null +++ b/crates/chainspec/src/constants/mod.rs @@ -0,0 +1,49 @@ +use crate::spec::DepositContract; +use alloy_primitives::{address, b256}; + +/// Deposit contract address: `0x00000000219ab540356cbb839cbe05303d7705fa` +pub(crate) const MAINNET_DEPOSIT_CONTRACT: DepositContract = DepositContract::new( + address!("00000000219ab540356cbb839cbe05303d7705fa"), + 11052984, + b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"), +); + +#[cfg(feature = "optimism")] +pub(crate) mod optimism; + +#[cfg(test)] +mod tests { + use alloy_eips::calc_next_block_base_fee; + + #[test] + fn calculate_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + crate::BaseFeeParams::ethereum(), + ) as u64 + ); + } + } +} diff --git a/crates/chainspec/src/constants/optimism.rs b/crates/chainspec/src/constants/optimism.rs new file mode 100644 index 000000000..d4a1de6d0 --- /dev/null +++ b/crates/chainspec/src/constants/optimism.rs @@ -0,0 +1,148 @@ +use alloy_eips::eip1559::BaseFeeParams; +use reth_primitives_traits::constants::{ + BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, + OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +/// Get the base fee parameters for Base Sepolia. +pub(crate) const BASE_SEPOLIA_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { + max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +/// Get the base fee parameters for Base Sepolia (post Canyon). +pub(crate) const BASE_SEPOLIA_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { + max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + elasticity_multiplier: BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +/// Get the base fee parameters for Optimism Sepolia. +pub(crate) const OP_SEPOLIA_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { + max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +/// Get the base fee parameters for Optimism Sepolia (post Canyon). +pub(crate) const OP_SEPOLIA_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { + max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +/// Get the base fee parameters for Optimism Mainnet. +pub(crate) const OP_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { + max_change_denominator: OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, + elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +/// Get the base fee parameters for Optimism Mainnet (post Canyon). +pub(crate) const OP_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { + max_change_denominator: OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, + elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, +}; + +#[cfg(test)] +mod tests { + use super::*; + use alloy_eips::calc_next_block_base_fee; + + #[test] + fn calculate_optimism_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + OP_BASE_FEE_PARAMS, + ) as u64 + ); + } + } + + #[test] + fn calculate_optimism_sepolia_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + OP_SEPOLIA_BASE_FEE_PARAMS, + ) as u64 + ); + } + } + + #[test] + fn calculate_base_sepolia_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1180000000, 1146666666, 1122857142, 1244299375, 1189416692, 1028254188, 1144836295, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + BASE_SEPOLIA_BASE_FEE_PARAMS, + ) as u64 + ); + } + } +} diff --git a/crates/primitives/src/chain/info.rs b/crates/chainspec/src/info.rs similarity index 86% rename from crates/primitives/src/chain/info.rs rename to crates/chainspec/src/info.rs index 38b73e276..6fe82d0a2 100644 --- a/crates/primitives/src/chain/info.rs +++ b/crates/chainspec/src/info.rs @@ -1,4 +1,5 @@ -use crate::{BlockNumHash, BlockNumber, B256}; +use alloy_eips::BlockNumHash; +use alloy_primitives::{BlockNumber, B256}; /// Current status of the blockchain's head. #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] diff --git a/crates/primitives/src/chain/mod.rs b/crates/chainspec/src/lib.rs similarity index 82% rename from crates/primitives/src/chain/mod.rs rename to crates/chainspec/src/lib.rs index 41de1c450..61460aa30 100644 --- a/crates/primitives/src/chain/mod.rs +++ b/crates/chainspec/src/lib.rs @@ -1,3 +1,13 @@ +//! The spec of an Ethereum network + +#![doc( + html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", + html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", + issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/" +)] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] + pub use alloy_chains::{Chain, ChainKind, NamedChain}; pub use info::ChainInfo; pub use spec::{ @@ -8,21 +18,24 @@ pub use spec::{ #[cfg(feature = "optimism")] pub use spec::{BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA}; -#[cfg(feature = "optimism")] -#[cfg(test)] -pub(crate) use spec::{ - BASE_SEPOLIA_BASE_FEE_PARAMS, OP_BASE_FEE_PARAMS, OP_SEPOLIA_BASE_FEE_PARAMS, -}; - -// The chain spec module. -mod spec; -// The chain info module. +// /// The config info module namely spec id. +// pub mod config; +/// The chain info module. mod info; +/// Network related constants +pub mod net; + +/// The chain spec module. +mod spec; + +/// Chain specific constants +pub(crate) mod constants; + #[cfg(test)] mod tests { use super::*; - use crate::U256; + use alloy_primitives::U256; use alloy_rlp::Encodable; use std::str::FromStr; diff --git a/crates/primitives/src/net.rs b/crates/chainspec/src/net.rs similarity index 100% rename from crates/primitives/src/net.rs rename to crates/chainspec/src/net.rs diff --git a/crates/primitives/src/chain/spec.rs b/crates/chainspec/src/spec.rs similarity index 98% rename from crates/primitives/src/chain/spec.rs rename to crates/chainspec/src/spec.rs index 788acf7b1..2462da93a 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/chainspec/src/spec.rs @@ -1,24 +1,4 @@ -use crate::{ - constants::{ - EIP1559_INITIAL_BASE_FEE, EMPTY_RECEIPTS, EMPTY_ROOT_HASH, EMPTY_TRANSACTIONS, - EMPTY_WITHDRAWALS, - }, - holesky_nodes, - net::{goerli_nodes, mainnet_nodes, sepolia_nodes}, - revm_primitives::{address, b256}, - Address, BlockNumber, Chain, ChainKind, ForkFilter, ForkFilterKey, ForkHash, ForkId, Genesis, - Hardfork, Head, Header, NamedChain, NodeRecord, SealedHeader, B256, EMPTY_OMMER_ROOT_HASH, - MAINNET_DEPOSIT_CONTRACT, U256, -}; -use core::{ - fmt, - fmt::{Display, Formatter}, -}; -use derive_more::From; -use once_cell::sync::Lazy; -use reth_trie_common::root::state_root_ref_unhashed; -use serde::{Deserialize, Serialize}; - +use crate::constants::MAINNET_DEPOSIT_CONTRACT; #[cfg(not(feature = "std"))] use alloc::{ collections::BTreeMap, @@ -27,25 +7,46 @@ use alloc::{ sync::Arc, vec::Vec, }; +use alloy_chains::{Chain, ChainKind, NamedChain}; +use alloy_genesis::Genesis; +use alloy_primitives::{address, b256, Address, BlockNumber, B256, U256}; +use alloy_trie::EMPTY_ROOT_HASH; +use core::{ + fmt, + fmt::{Display, Formatter}, +}; +use derive_more::From; +use once_cell::sync::Lazy; +use reth_ethereum_forks::{ForkFilter, ForkFilterKey, ForkHash, ForkId, Hardfork, Head}; +use reth_network_peers::NodeRecord; +use reth_primitives_traits::{ + constants::{ + EIP1559_INITIAL_BASE_FEE, EMPTY_OMMER_ROOT_HASH, EMPTY_RECEIPTS, EMPTY_TRANSACTIONS, + EMPTY_WITHDRAWALS, + }, + Header, SealedHeader, +}; +use reth_trie_common::root::state_root_ref_unhashed; +use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use std::{collections::BTreeMap, sync::Arc}; +#[cfg(feature = "optimism")] +use crate::constants::optimism::{ + BASE_SEPOLIA_BASE_FEE_PARAMS, BASE_SEPOLIA_CANYON_BASE_FEE_PARAMS, OP_BASE_FEE_PARAMS, + OP_CANYON_BASE_FEE_PARAMS, OP_SEPOLIA_BASE_FEE_PARAMS, OP_SEPOLIA_CANYON_BASE_FEE_PARAMS, +}; pub use alloy_eips::eip1559::BaseFeeParams; #[cfg(feature = "optimism")] -pub(crate) use crate::{ - constants::{ - BASE_SEPOLIA_BASE_FEE_PARAMS, BASE_SEPOLIA_CANYON_BASE_FEE_PARAMS, OP_BASE_FEE_PARAMS, - OP_CANYON_BASE_FEE_PARAMS, OP_SEPOLIA_BASE_FEE_PARAMS, OP_SEPOLIA_CANYON_BASE_FEE_PARAMS, - }, - net::{base_nodes, base_testnet_nodes, op_nodes, op_testnet_nodes}, -}; +use crate::net::{base_nodes, base_testnet_nodes, op_nodes, op_testnet_nodes}; +use crate::net::{goerli_nodes, holesky_nodes, mainnet_nodes, sepolia_nodes}; /// The Ethereum mainnet spec pub static MAINNET: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::mainnet(), - genesis: serde_json::from_str(include_str!("../../res/genesis/mainnet.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/mainnet.json")) .expect("Can't deserialize Mainnet genesis json"), genesis_hash: Some(b256!( "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" @@ -96,7 +97,7 @@ pub static MAINNET: Lazy> = Lazy::new(|| { pub static GOERLI: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::goerli(), - genesis: serde_json::from_str(include_str!("../../res/genesis/goerli.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/goerli.json")) .expect("Can't deserialize Goerli genesis json"), genesis_hash: Some(b256!( "bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a" @@ -138,7 +139,7 @@ pub static GOERLI: Lazy> = Lazy::new(|| { pub static SEPOLIA: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::sepolia(), - genesis: serde_json::from_str(include_str!("../../res/genesis/sepolia.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/sepolia.json")) .expect("Can't deserialize Sepolia genesis json"), genesis_hash: Some(b256!( "25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9" @@ -184,7 +185,7 @@ pub static SEPOLIA: Lazy> = Lazy::new(|| { pub static HOLESKY: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::holesky(), - genesis: serde_json::from_str(include_str!("../../res/genesis/holesky.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/holesky.json")) .expect("Can't deserialize Holesky genesis json"), genesis_hash: Some(b256!( "b5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4" @@ -228,7 +229,7 @@ pub static HOLESKY: Lazy> = Lazy::new(|| { pub static DEV: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::dev(), - genesis: serde_json::from_str(include_str!("../../res/genesis/dev.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/dev.json")) .expect("Can't deserialize Dev testnet genesis json"), genesis_hash: Some(b256!( "2f980576711e3617a5e4d83dd539548ec0f7792007d505a3d2e9674833af2d7c" @@ -274,7 +275,7 @@ pub static OP_MAINNET: Lazy> = Lazy::new(|| { chain: Chain::optimism_mainnet(), // genesis contains empty alloc field because state at first bedrock block is imported // manually from trusted source - genesis: serde_json::from_str(include_str!("../../res/genesis/optimism.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/optimism.json")) .expect("Can't deserialize Optimism Mainnet genesis json"), genesis_hash: Some(b256!( "7ca38a1916c42007829c55e69d3e9a73265554b586a499015373241b8a3fa48b" @@ -324,7 +325,7 @@ pub static OP_MAINNET: Lazy> = Lazy::new(|| { pub static OP_SEPOLIA: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::from_named(NamedChain::OptimismSepolia), - genesis: serde_json::from_str(include_str!("../../res/genesis/sepolia_op.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/sepolia_op.json")) .expect("Can't deserialize OP Sepolia genesis json"), genesis_hash: Some(b256!( "102de6ffb001480cc9b8b548fd05c34cd4f46ae4aa91759393db90ea0409887d" @@ -374,7 +375,7 @@ pub static OP_SEPOLIA: Lazy> = Lazy::new(|| { pub static BASE_SEPOLIA: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::base_sepolia(), - genesis: serde_json::from_str(include_str!("../../res/genesis/sepolia_base.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/sepolia_base.json")) .expect("Can't deserialize Base Sepolia genesis json"), genesis_hash: Some(b256!( "0dcc9e089e30b90ddfc55be9a37dd15bc551aeee999d2e2b51414c54eaf934e4" @@ -424,7 +425,7 @@ pub static BASE_SEPOLIA: Lazy> = Lazy::new(|| { pub static BASE_MAINNET: Lazy> = Lazy::new(|| { ChainSpec { chain: Chain::base_mainnet(), - genesis: serde_json::from_str(include_str!("../../res/genesis/base.json")) + genesis: serde_json::from_str(include_str!("../res/genesis/base.json")) .expect("Can't deserialize Base genesis json"), genesis_hash: Some(b256!( "f712aa9241cc24369b143cf6dce85f0902a9731e70d66818a3a5845b296c73dd" @@ -852,12 +853,6 @@ impl ChainSpec { self.fork(Hardfork::Homestead).active_at_block(block_number) } - /// The Paris hardfork (merge) is activated via ttd, if we know the block is known then this - /// returns true if the block number is greater than or equal to the Paris (merge) block. - pub fn is_paris_active_at_block(&self, block_number: u64) -> Option { - self.paris_block_and_final_difficulty.map(|(paris_block, _)| block_number >= paris_block) - } - /// Convenience method to check if [`Hardfork::Bedrock`] is active at a given block number. #[cfg(feature = "optimism")] #[inline] @@ -1523,7 +1518,7 @@ impl Display for DisplayFork { /// # Examples /// /// ``` -/// # use reth_primitives::MAINNET; +/// # use reth_chainspec::MAINNET; /// println!("{}", MAINNET.display_hardforks()); /// ``` /// @@ -1737,11 +1732,15 @@ impl OptimismGenesisInfo { #[cfg(test)] mod tests { + use alloy_chains::Chain; + use alloy_genesis::{ChainConfig, GenesisAccount}; + use reth_ethereum_forks::{ForkHash, ForkId, Head}; use reth_trie_common::TrieAccount; use super::*; - use crate::{b256, hex, ChainConfig, GenesisAccount}; + use alloy_primitives::{b256, hex}; use std::{collections::HashMap, str::FromStr}; + fn test_fork_ids(spec: &ChainSpec, cases: &[(Head, ForkId)]) { for (block, expected_id) in cases { let computed_id = spec.fork_id(block); diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 90fdb0e3e..ff3cf0169 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -16,14 +16,13 @@ workspace = true reth-primitives-traits.workspace = true reth-codecs.workspace = true reth-ethereum-forks.workspace = true -reth-network-peers.workspace = true reth-static-file-types.workspace = true reth-trie-common.workspace = true +reth-chainspec.workspace = true revm.workspace = true revm-primitives = { workspace = true, features = ["serde"] } # ethereum -alloy-chains = { workspace = true, features = ["serde", "rlp"] } alloy-consensus = { workspace = true, features = ["serde"] } alloy-primitives = { workspace = true, features = ["rand", "rlp"] } alloy-rlp = { workspace = true, features = ["arrayvec"] } @@ -48,7 +47,6 @@ modular-bitfield.workspace = true once_cell.workspace = true rayon.workspace = true serde.workspace = true -serde_json.workspace = true tempfile = { workspace = true, optional = true } thiserror-no-std = { workspace = true , default-features = false } zstd = { version = "0.13", features = ["experimental"], optional = true } @@ -92,10 +90,10 @@ asm-keccak = ["alloy-primitives/asm-keccak"] arbitrary = [ "reth-primitives-traits/arbitrary", "revm-primitives/arbitrary", + "reth-chainspec/arbitrary", "reth-ethereum-forks/arbitrary", "nybbles/arbitrary", "alloy-trie/arbitrary", - "alloy-chains/arbitrary", "alloy-consensus/arbitrary", "alloy-eips/arbitrary", "dep:arbitrary", @@ -112,6 +110,7 @@ c-kzg = [ ] zstd-codec = ["dep:zstd"] optimism = [ + "reth-chainspec/optimism", "reth-codecs/optimism", "reth-ethereum-forks/optimism", "revm/optimism", diff --git a/crates/primitives/src/basefee.rs b/crates/primitives/src/basefee.rs index 0bafb9c89..aa52b02a0 100644 --- a/crates/primitives/src/basefee.rs +++ b/crates/primitives/src/basefee.rs @@ -3,144 +3,3 @@ // re-export #[doc(inline)] pub use alloy_eips::eip1559::calc_next_block_base_fee; - -#[cfg(test)] -mod tests { - use super::*; - - #[cfg(feature = "optimism")] - use crate::chain::{ - BASE_SEPOLIA_BASE_FEE_PARAMS, OP_BASE_FEE_PARAMS, OP_SEPOLIA_BASE_FEE_PARAMS, - }; - - #[test] - fn calculate_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calc_next_block_base_fee( - gas_used[i] as u128, - gas_limit[i] as u128, - base_fee[i] as u128, - crate::BaseFeeParams::ethereum(), - ) as u64 - ); - } - } - - #[cfg(feature = "optimism")] - #[test] - fn calculate_optimism_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calc_next_block_base_fee( - gas_used[i] as u128, - gas_limit[i] as u128, - base_fee[i] as u128, - OP_BASE_FEE_PARAMS, - ) as u64 - ); - } - } - - #[cfg(feature = "optimism")] - #[test] - fn calculate_optimism_sepolia_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calc_next_block_base_fee( - gas_used[i] as u128, - gas_limit[i] as u128, - base_fee[i] as u128, - OP_SEPOLIA_BASE_FEE_PARAMS, - ) as u64 - ); - } - } - - #[cfg(feature = "optimism")] - #[test] - fn calculate_base_sepolia_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1180000000, 1146666666, 1122857142, 1244299375, 1189416692, 1028254188, 1144836295, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calc_next_block_base_fee( - gas_used[i] as u128, - gas_limit[i] as u128, - base_fee[i] as u128, - BASE_SEPOLIA_BASE_FEE_PARAMS, - ) as u64 - ); - } - } -} diff --git a/crates/primitives/src/constants/mod.rs b/crates/primitives/src/constants/mod.rs index 41a26d609..d03303edc 100644 --- a/crates/primitives/src/constants/mod.rs +++ b/crates/primitives/src/constants/mod.rs @@ -1,70 +1,13 @@ //! Ethereum protocol-related constants -use crate::{ - chain::DepositContract, - revm_primitives::{address, b256}, -}; - pub use reth_primitives_traits::constants::*; -#[cfg(feature = "optimism")] -use crate::chain::BaseFeeParams; - /// Gas units, for example [`GIGAGAS`](gas_units::GIGAGAS). pub mod gas_units; /// [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#parameters) constants. pub mod eip4844; -/// Deposit contract address: `0x00000000219ab540356cbb839cbe05303d7705fa` -pub const MAINNET_DEPOSIT_CONTRACT: DepositContract = DepositContract::new( - address!("00000000219ab540356cbb839cbe05303d7705fa"), - 11052984, - b256!("649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5"), -); - -/// Get the base fee parameters for Base Sepolia. -#[cfg(feature = "optimism")] -pub const BASE_SEPOLIA_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, - elasticity_multiplier: BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Base Sepolia (post Canyon). -#[cfg(feature = "optimism")] -pub const BASE_SEPOLIA_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, - elasticity_multiplier: BASE_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Sepolia. -#[cfg(feature = "optimism")] -pub const OP_SEPOLIA_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_SEPOLIA_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, - elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Sepolia (post Canyon). -#[cfg(feature = "optimism")] -pub const OP_SEPOLIA_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_SEPOLIA_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, - elasticity_multiplier: OP_SEPOLIA_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Mainnet. -#[cfg(feature = "optimism")] -pub const OP_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_MAINNET_EIP1559_DEFAULT_BASE_FEE_MAX_CHANGE_DENOMINATOR, - elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - -/// Get the base fee parameters for Optimism Mainnet (post Canyon). -#[cfg(feature = "optimism")] -pub const OP_CANYON_BASE_FEE_PARAMS: BaseFeeParams = BaseFeeParams { - max_change_denominator: OP_MAINNET_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_CANYON, - elasticity_multiplier: OP_MAINNET_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER, -}; - #[cfg(test)] mod tests { use super::*; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index e73670826..184ba3bf0 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -27,7 +27,6 @@ mod account; mod alloy_compat; pub mod basefee; mod block; -mod chain; #[cfg(feature = "zstd-codec")] mod compression; pub mod constants; @@ -37,7 +36,6 @@ pub mod genesis; pub mod header; mod integer_list; mod log; -mod net; pub mod proofs; mod receipt; mod request; @@ -54,31 +52,31 @@ pub use block::{ Block, BlockBody, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, BlockWithSenders, ForkBlock, RpcBlockHash, SealedBlock, SealedBlockWithSenders, }; -pub use chain::{ - AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, Chain, ChainInfo, ChainKind, ChainSpec, - ChainSpecBuilder, DepositContract, DisplayHardforks, ForkBaseFeeParams, ForkCondition, - NamedChain, DEV, GOERLI, HOLESKY, MAINNET, SEPOLIA, -}; #[cfg(feature = "zstd-codec")] pub use compression::*; pub use constants::{ DEV_GENESIS_HASH, EMPTY_OMMER_ROOT_HASH, GOERLI_GENESIS_HASH, HOLESKY_GENESIS_HASH, - KECCAK_EMPTY, MAINNET_DEPOSIT_CONTRACT, MAINNET_GENESIS_HASH, SEPOLIA_GENESIS_HASH, + KECCAK_EMPTY, MAINNET_GENESIS_HASH, SEPOLIA_GENESIS_HASH, }; pub use error::{GotExpected, GotExpectedBoxed}; pub use genesis::{ChainConfig, Genesis, GenesisAccount}; pub use header::{Header, HeadersDirection, SealedHeader}; pub use integer_list::IntegerList; pub use log::{logs_bloom, Log}; -pub use net::{ - goerli_nodes, holesky_nodes, mainnet_nodes, parse_nodes, sepolia_nodes, NodeRecord, - NodeRecordParseError, TrustedPeer, GOERLI_BOOTNODES, HOLESKY_BOOTNODES, MAINNET_BOOTNODES, - SEPOLIA_BOOTNODES, -}; pub use receipt::{ gas_spent_by_transactions, Receipt, ReceiptWithBloom, ReceiptWithBloomRef, Receipts, }; pub use request::Requests; +pub use reth_chainspec::{ + net::{ + goerli_nodes, holesky_nodes, mainnet_nodes, parse_nodes, sepolia_nodes, NodeRecord, + NodeRecordParseError, TrustedPeer, GOERLI_BOOTNODES, HOLESKY_BOOTNODES, MAINNET_BOOTNODES, + SEPOLIA_BOOTNODES, + }, + AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, Chain, ChainInfo, ChainKind, ChainSpec, + ChainSpecBuilder, DepositContract, DisplayHardforks, ForkBaseFeeParams, ForkCondition, + NamedChain, DEV, GOERLI, HOLESKY, MAINNET, SEPOLIA, +}; pub use static_file::StaticFileSegment; pub use storage::StorageEntry; @@ -140,13 +138,13 @@ pub use c_kzg as kzg; /// Optimism specific re-exports #[cfg(feature = "optimism")] mod optimism { - pub use crate::{ - chain::{BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA}, + pub use crate::transaction::{TxDeposit, DEPOSIT_TX_TYPE_ID}; + pub use reth_chainspec::{ net::{ base_nodes, base_testnet_nodes, op_nodes, op_testnet_nodes, OP_BOOTNODES, OP_TESTNET_BOOTNODES, }, - transaction::{TxDeposit, DEPOSIT_TX_TYPE_ID}, + BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA, }; }