mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
refactor: extract Chainspec type from primitives (#8055)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com> Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
This commit is contained in:
53
crates/chainspec/Cargo.toml
Normal file
53
crates/chainspec/Cargo.toml
Normal file
@ -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"
|
||||
]
|
||||
|
||||
|
||||
1
crates/chainspec/res/genesis/base.json
Normal file
1
crates/chainspec/res/genesis/base.json
Normal file
File diff suppressed because one or more lines are too long
1
crates/chainspec/res/genesis/dev.json
Normal file
1
crates/chainspec/res/genesis/dev.json
Normal file
@ -0,0 +1 @@
|
||||
{"nonce":"0x0","timestamp":"0x6490fdd2","extraData":"0x","gasLimit":"0x1c9c380","difficulty":"0x0","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","stateRoot":"0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494","alloc":{"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266":{"balance":"0xD3C21BCECCEDA1000000"},"0x70997970C51812dc3A010C7d01b50e0d17dc79C8":{"balance":"0xD3C21BCECCEDA1000000"},"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC":{"balance":"0xD3C21BCECCEDA1000000"},"0x90F79bf6EB2c4f870365E785982E1f101E93b906":{"balance":"0xD3C21BCECCEDA1000000"},"0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65":{"balance":"0xD3C21BCECCEDA1000000"},"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc":{"balance":"0xD3C21BCECCEDA1000000"},"0x976EA74026E726554dB657fA54763abd0C3a0aa9":{"balance":"0xD3C21BCECCEDA1000000"},"0x14dC79964da2C08b23698B3D3cc7Ca32193d9955":{"balance":"0xD3C21BCECCEDA1000000"},"0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f":{"balance":"0xD3C21BCECCEDA1000000"},"0xa0Ee7A142d267C1f36714E4a8F75612F20a79720":{"balance":"0xD3C21BCECCEDA1000000"},"0xBcd4042DE499D14e55001CcbB24a551F3b954096":{"balance":"0xD3C21BCECCEDA1000000"},"0x71bE63f3384f5fb98995898A86B02Fb2426c5788":{"balance":"0xD3C21BCECCEDA1000000"},"0xFABB0ac9d68B0B445fB7357272Ff202C5651694a":{"balance":"0xD3C21BCECCEDA1000000"},"0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec":{"balance":"0xD3C21BCECCEDA1000000"},"0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097":{"balance":"0xD3C21BCECCEDA1000000"},"0xcd3B766CCDd6AE721141F452C550Ca635964ce71":{"balance":"0xD3C21BCECCEDA1000000"},"0x2546BcD3c84621e976D8185a91A922aE77ECEc30":{"balance":"0xD3C21BCECCEDA1000000"},"0xbDA5747bFD65F08deb54cb465eB87D40e51B197E":{"balance":"0xD3C21BCECCEDA1000000"},"0xdD2FD4581271e230360230F9337D5c0430Bf44C0":{"balance":"0xD3C21BCECCEDA1000000"},"0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199":{"balance":"0xD3C21BCECCEDA1000000"}},"number":"0x0","gasUsed":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
1
crates/chainspec/res/genesis/goerli.json
Normal file
1
crates/chainspec/res/genesis/goerli.json
Normal file
File diff suppressed because one or more lines are too long
1
crates/chainspec/res/genesis/holesky.json
Normal file
1
crates/chainspec/res/genesis/holesky.json
Normal file
File diff suppressed because one or more lines are too long
1
crates/chainspec/res/genesis/mainnet.json
Normal file
1
crates/chainspec/res/genesis/mainnet.json
Normal file
File diff suppressed because one or more lines are too long
1
crates/chainspec/res/genesis/optimism.json
Normal file
1
crates/chainspec/res/genesis/optimism.json
Normal file
@ -0,0 +1 @@
|
||||
{"config":{"ChainName":"optimism-mainnet","chainId":10,"homesteadBlock":0,"eip150Block":0,"eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"berlinBlock":3950000,"londonBlock":105235063,"arrowGlacierBlock":105235063,"grayGlacierBlock":105235063,"mergeNetsplitBlock":105235063,"bedrockBlock":105235063,"terminalTotalDifficulty":0,"terminalTotalDifficultyPassed":true,"optimism":{"eip1559Elasticity":6,"eip1559Denominator":50},"regolithTime":0},"difficulty":"1","gasLimit":"15000000","extradata":"0x000000000000000000000000000000000000000000000000000000000000000000000398232e2064f896018496b4b44b3d62751f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","stateRoot":"0xeddb4c1786789419153a27c4c80ff44a2226b6eda04f7e22ce5bae892ea568eb","alloc":{}}
|
||||
1
crates/chainspec/res/genesis/sepolia.json
Normal file
1
crates/chainspec/res/genesis/sepolia.json
Normal file
@ -0,0 +1 @@
|
||||
{"nonce":"0x00","timestamp":"0x6159af19","extraData":"0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521","gasLimit":"0x1c9c380","difficulty":"0x20000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","stateRoot":"0x5eb6e371a698b8d68f665192350ffcecbbbf322916f4b51bd79bb6887da3f494","alloc":{"0xa2A6d93439144FFE4D27c9E088dCD8b783946263":{"balance":"0xD3C21BCECCEDA1000000"},"0xBc11295936Aa79d594139de1B2e12629414F3BDB":{"balance":"0xD3C21BCECCEDA1000000"},"0x7cF5b79bfe291A67AB02b393E456cCc4c266F753":{"balance":"0xD3C21BCECCEDA1000000"},"0xaaec86394441f915bce3e6ab399977e9906f3b69":{"balance":"0xD3C21BCECCEDA1000000"},"0xF47CaE1CF79ca6758Bfc787dbD21E6bdBe7112B8":{"balance":"0xD3C21BCECCEDA1000000"},"0xd7eDDB78ED295B3C9629240E8924fb8D8874ddD8":{"balance":"0xD3C21BCECCEDA1000000"},"0x8b7F0977Bb4f0fBE7076FA22bC24acA043583F5e":{"balance":"0xD3C21BCECCEDA1000000"},"0xe2e2659028143784d557bcec6ff3a0721048880a":{"balance":"0xD3C21BCECCEDA1000000"},"0xd9a5179f091d85051d3c982785efd1455cec8699":{"balance":"0xD3C21BCECCEDA1000000"},"0xbeef32ca5b9a198d27B4e02F4c70439fE60356Cf":{"balance":"0xD3C21BCECCEDA1000000"},"0x0000006916a87b82333f4245046623b23794c65c":{"balance":"0x84595161401484A000000"},"0xb21c33de1fab3fa15499c62b59fe0cc3250020d1":{"balance":"0x52B7D2DCC80CD2E4000000"},"0x10F5d45854e038071485AC9e402308cF80D2d2fE":{"balance":"0x52B7D2DCC80CD2E4000000"},"0xd7d76c58b3a519e9fA6Cc4D22dC017259BC49F1E":{"balance":"0x52B7D2DCC80CD2E4000000"},"0x799D329e5f583419167cD722962485926E338F4a":{"balance":"0xDE0B6B3A7640000"}},"number":"0x0","gasUsed":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}
|
||||
1
crates/chainspec/res/genesis/sepolia_base.json
Normal file
1
crates/chainspec/res/genesis/sepolia_base.json
Normal file
File diff suppressed because one or more lines are too long
1
crates/chainspec/res/genesis/sepolia_op.json
Normal file
1
crates/chainspec/res/genesis/sepolia_op.json
Normal file
File diff suppressed because one or more lines are too long
49
crates/chainspec/src/constants/mod.rs
Normal file
49
crates/chainspec/src/constants/mod.rs
Normal file
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
148
crates/chainspec/src/constants/optimism.rs
Normal file
148
crates/chainspec/src/constants/optimism.rs
Normal file
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
crates/chainspec/src/info.rs
Normal file
17
crates/chainspec/src/info.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use alloy_eips::BlockNumHash;
|
||||
use alloy_primitives::{BlockNumber, B256};
|
||||
|
||||
/// Current status of the blockchain's head.
|
||||
#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ChainInfo {
|
||||
/// The block hash of the highest fully synced block.
|
||||
pub best_hash: B256,
|
||||
/// The block number of the highest fully synced block.
|
||||
pub best_number: BlockNumber,
|
||||
}
|
||||
|
||||
impl From<ChainInfo> for BlockNumHash {
|
||||
fn from(value: ChainInfo) -> Self {
|
||||
Self { number: value.best_number, hash: value.best_hash }
|
||||
}
|
||||
}
|
||||
137
crates/chainspec/src/lib.rs
Normal file
137
crates/chainspec/src/lib.rs
Normal file
@ -0,0 +1,137 @@
|
||||
//! 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::{
|
||||
AllGenesisFormats, BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder,
|
||||
DepositContract, DisplayHardforks, ForkBaseFeeParams, ForkCondition, DEV, GOERLI, HOLESKY,
|
||||
MAINNET, SEPOLIA,
|
||||
};
|
||||
#[cfg(feature = "optimism")]
|
||||
pub use spec::{BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA};
|
||||
|
||||
// /// 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 alloy_primitives::U256;
|
||||
use alloy_rlp::Encodable;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_id() {
|
||||
let chain = Chain::from(1234);
|
||||
assert_eq!(chain.id(), 1234);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_named_id() {
|
||||
let chain = Chain::from_named(NamedChain::Goerli);
|
||||
assert_eq!(chain.id(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_named_chain() {
|
||||
let chain = Chain::from_named(NamedChain::Mainnet);
|
||||
assert_eq!(format!("{chain}"), "mainnet");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_id_chain() {
|
||||
let chain = Chain::from(1234);
|
||||
assert_eq!(format!("{chain}"), "1234");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_u256() {
|
||||
let n = U256::from(1234);
|
||||
let chain = Chain::from(n.to::<u64>());
|
||||
let expected = Chain::from(1234);
|
||||
|
||||
assert_eq!(chain, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_u256() {
|
||||
let chain = Chain::from_named(NamedChain::Goerli);
|
||||
let n: U256 = U256::from(chain.id());
|
||||
let expected = U256::from(5);
|
||||
|
||||
assert_eq!(n, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_named_chain() {
|
||||
let result = Chain::from_str("mainnet");
|
||||
let expected = Chain::from_named(NamedChain::Mainnet);
|
||||
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_named_chain_error() {
|
||||
let result = Chain::from_str("chain");
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_id_chain() {
|
||||
let result = Chain::from_str("1234");
|
||||
let expected = Chain::from(1234);
|
||||
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default() {
|
||||
let default = Chain::default();
|
||||
let expected = Chain::from_named(NamedChain::Mainnet);
|
||||
|
||||
assert_eq!(default, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_id_chain_encodable_length() {
|
||||
let chain = Chain::from(1234);
|
||||
|
||||
assert_eq!(chain.length(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dns_main_network() {
|
||||
let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net";
|
||||
let chain: Chain = NamedChain::Mainnet.into();
|
||||
assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dns_holesky_network() {
|
||||
let s = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net";
|
||||
let chain: Chain = NamedChain::Holesky.into();
|
||||
assert_eq!(s, chain.public_dns_network_protocol().unwrap().as_str());
|
||||
}
|
||||
}
|
||||
250
crates/chainspec/src/net.rs
Normal file
250
crates/chainspec/src/net.rs
Normal file
@ -0,0 +1,250 @@
|
||||
pub use reth_network_peers::{NodeRecord, NodeRecordParseError, TrustedPeer};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
// Ethereum bootnodes come from <https://github.com/ledgerwatch/erigon/blob/devel/params/bootnodes.go>
|
||||
// OP bootnodes come from <https://github.com/ethereum-optimism/op-geth/blob/optimism/params/bootnodes.go>
|
||||
|
||||
/// Ethereum Foundation Go Bootnodes
|
||||
pub static MAINNET_BOOTNODES : [&str; 4] = [
|
||||
"enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", // bootnode-aws-ap-southeast-1-001
|
||||
"enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", // bootnode-aws-us-east-1-001
|
||||
"enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", // bootnode-hetzner-hel
|
||||
"enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", // bootnode-hetzner-fsn
|
||||
];
|
||||
|
||||
/// Ethereum Foundation Sepolia Bootnodes
|
||||
pub static SEPOLIA_BOOTNODES : [&str; 5] = [
|
||||
"enode://4e5e92199ee224a01932a377160aa432f31d0b351f84ab413a8e0a42f4f36476f8fb1cbe914af0d9aef0d51665c214cf653c651c4bbd9d5550a934f241f1682b@138.197.51.181:30303", // sepolia-bootnode-1-nyc3
|
||||
"enode://143e11fb766781d22d92a2e33f8f104cddae4411a122295ed1fdb6638de96a6ce65f5b7c964ba3763bba27961738fef7d3ecc739268f3e5e771fb4c87b6234ba@146.190.1.103:30303", // sepolia-bootnode-1-sfo3
|
||||
"enode://8b61dc2d06c3f96fddcbebb0efb29d60d3598650275dc469c22229d3e5620369b0d3dedafd929835fe7f489618f19f456fe7c0df572bf2d914a9f4e006f783a9@170.64.250.88:30303", // sepolia-bootnode-1-syd1
|
||||
"enode://10d62eff032205fcef19497f35ca8477bea0eadfff6d769a147e895d8b2b8f8ae6341630c645c30f5df6e67547c03494ced3d9c5764e8622a26587b083b028e8@139.59.49.206:30303", // sepolia-bootnode-1-blr1
|
||||
"enode://9e9492e2e8836114cc75f5b929784f4f46c324ad01daf87d956f98b3b6c5fcba95524d6e5cf9861dc96a2c8a171ea7105bb554a197455058de185fa870970c7c@138.68.123.152:30303", // sepolia-bootnode-1-ams3
|
||||
];
|
||||
|
||||
/// Görli Bootnodes
|
||||
pub static GOERLI_BOOTNODES : [&str; 7] = [
|
||||
// Upstream bootnodes
|
||||
"enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303",
|
||||
"enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303",
|
||||
"enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313",
|
||||
"enode://b5948a2d3e9d486c4d75bf32713221c2bd6cf86463302339299bd227dc2e276cd5a1c7ca4f43a0e9122fe9af884efed563bd2a1fd28661f3b5f5ad7bf1de5949@18.218.250.66:30303",
|
||||
|
||||
// Ethereum Foundation bootnode
|
||||
"enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303",
|
||||
|
||||
// Goerli Initiative bootnodes
|
||||
"enode://d4f764a48ec2a8ecf883735776fdefe0a3949eb0ca476bd7bc8d0954a9defe8fea15ae5da7d40b5d2d59ce9524a99daedadf6da6283fca492cc80b53689fb3b3@46.4.99.122:32109",
|
||||
"enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303",
|
||||
];
|
||||
|
||||
/// Ethereum Foundation Holesky Bootnodes
|
||||
pub static HOLESKY_BOOTNODES : [&str; 2] = [
|
||||
"enode://ac906289e4b7f12df423d654c5a962b6ebe5b3a74cc9e06292a85221f9a64a6f1cfdd6b714ed6dacef51578f92b34c60ee91e9ede9c7f8fadc4d347326d95e2b@146.190.13.128:30303",
|
||||
"enode://a3435a0155a3e837c02f5e7f5662a2f1fbc25b48e4dc232016e1c51b544cb5b4510ef633ea3278c0e970fa8ad8141e2d4d0f9f95456c537ff05fdf9b31c15072@178.128.136.233:30303",
|
||||
];
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
/// OP stack mainnet boot nodes.
|
||||
pub static OP_BOOTNODES: &[&str] = &[
|
||||
// OP Labs
|
||||
"enode://ca2774c3c401325850b2477fd7d0f27911efbf79b1e8b335066516e2bd8c4c9e0ba9696a94b1cb030a88eac582305ff55e905e64fb77fe0edcd70a4e5296d3ec@34.65.175.185:30305",
|
||||
"enode://dd751a9ef8912be1bfa7a5e34e2c3785cc5253110bd929f385e07ba7ac19929fb0e0c5d93f77827291f4da02b2232240fbc47ea7ce04c46e333e452f8656b667@34.65.107.0:30305",
|
||||
"enode://c5d289b56a77b6a2342ca29956dfd07aadf45364dde8ab20d1dc4efd4d1bc6b4655d902501daea308f4d8950737a4e93a4dfedd17b49cd5760ffd127837ca965@34.65.202.239:30305",
|
||||
// Base
|
||||
"enode://87a32fd13bd596b2ffca97020e31aef4ddcc1bbd4b95bb633d16c1329f654f34049ed240a36b449fda5e5225d70fe40bc667f53c304b71f8e68fc9d448690b51@3.231.138.188:30301",
|
||||
"enode://ca21ea8f176adb2e229ce2d700830c844af0ea941a1d8152a9513b966fe525e809c3a6c73a2c18a12b74ed6ec4380edf91662778fe0b79f6a591236e49e176f9@184.72.129.189:30301",
|
||||
"enode://acf4507a211ba7c1e52cdf4eef62cdc3c32e7c9c47998954f7ba024026f9a6b2150cd3f0b734d9c78e507ab70d59ba61dfe5c45e1078c7ad0775fb251d7735a2@3.220.145.177:30301",
|
||||
"enode://8a5a5006159bf079d06a04e5eceab2a1ce6e0f721875b2a9c96905336219dbe14203d38f70f3754686a6324f786c2f9852d8c0dd3adac2d080f4db35efc678c5@3.231.11.52:30301",
|
||||
"enode://cdadbe835308ad3557f9a1de8db411da1a260a98f8421d62da90e71da66e55e98aaa8e90aa7ce01b408a54e4bd2253d701218081ded3dbe5efbbc7b41d7cef79@54.198.153.150:30301"
|
||||
];
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
/// OP stack testnet boot nodes.
|
||||
pub static OP_TESTNET_BOOTNODES: &[&str] = &[
|
||||
// OP Labs
|
||||
"enode://2bd2e657bb3c8efffb8ff6db9071d9eb7be70d7c6d7d980ff80fc93b2629675c5f750bc0a5ef27cd788c2e491b8795a7e9a4a6e72178c14acc6753c0e5d77ae4@34.65.205.244:30305",
|
||||
"enode://db8e1cab24624cc62fc35dbb9e481b88a9ef0116114cd6e41034c55b5b4f18755983819252333509bd8e25f6b12aadd6465710cd2e956558faf17672cce7551f@34.65.173.88:30305",
|
||||
"enode://bfda2e0110cfd0f4c9f7aa5bf5ec66e6bd18f71a2db028d36b8bf8b0d6fdb03125c1606a6017b31311d96a36f5ef7e1ad11604d7a166745e6075a715dfa67f8a@34.65.229.245:30305",
|
||||
// Base
|
||||
"enode://548f715f3fc388a7c917ba644a2f16270f1ede48a5d88a4d14ea287cc916068363f3092e39936f1a3e7885198bef0e5af951f1d7b1041ce8ba4010917777e71f@18.210.176.114:30301",
|
||||
"enode://6f10052847a966a725c9f4adf6716f9141155b99a0fb487fea3f51498f4c2a2cb8d534e680ee678f9447db85b93ff7c74562762c3714783a7233ac448603b25f@107.21.251.55:30301",
|
||||
];
|
||||
|
||||
/// Returns parsed mainnet nodes
|
||||
pub fn mainnet_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(&MAINNET_BOOTNODES[..])
|
||||
}
|
||||
|
||||
/// Returns parsed goerli nodes
|
||||
pub fn goerli_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(&GOERLI_BOOTNODES[..])
|
||||
}
|
||||
|
||||
/// Returns parsed sepolia nodes
|
||||
pub fn sepolia_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(&SEPOLIA_BOOTNODES[..])
|
||||
}
|
||||
|
||||
/// Returns parsed holesky nodes
|
||||
pub fn holesky_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(&HOLESKY_BOOTNODES[..])
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
/// Returns parsed op-stack mainnet nodes
|
||||
pub fn op_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(OP_BOOTNODES)
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
/// Returns parsed op-stack testnet nodes
|
||||
pub fn op_testnet_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(OP_TESTNET_BOOTNODES)
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
/// Returns parsed op-stack base mainnet nodes
|
||||
pub fn base_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(OP_BOOTNODES)
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
/// Returns parsed op-stack base testnet nodes
|
||||
pub fn base_testnet_nodes() -> Vec<NodeRecord> {
|
||||
parse_nodes(OP_TESTNET_BOOTNODES)
|
||||
}
|
||||
|
||||
/// Parses all the nodes
|
||||
pub fn parse_nodes(nodes: impl IntoIterator<Item = impl AsRef<str>>) -> Vec<NodeRecord> {
|
||||
nodes.into_iter().map(|s| s.as_ref().parse().unwrap()).collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloy_rlp::Decodable;
|
||||
use rand::{thread_rng, Rng, RngCore};
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
#[test]
|
||||
fn test_mapped_ipv6() {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let v4: Ipv4Addr = "0.0.0.0".parse().unwrap();
|
||||
let v6 = v4.to_ipv6_mapped();
|
||||
|
||||
let record = NodeRecord {
|
||||
address: v6.into(),
|
||||
tcp_port: rng.gen(),
|
||||
udp_port: rng.gen(),
|
||||
id: rng.gen(),
|
||||
};
|
||||
|
||||
assert!(record.clone().convert_ipv4_mapped());
|
||||
assert_eq!(record.into_ipv4_mapped().address, IpAddr::from(v4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mapped_ipv4() {
|
||||
let mut rng = thread_rng();
|
||||
let v4: Ipv4Addr = "0.0.0.0".parse().unwrap();
|
||||
|
||||
let record = NodeRecord {
|
||||
address: v4.into(),
|
||||
tcp_port: rng.gen(),
|
||||
udp_port: rng.gen(),
|
||||
id: rng.gen(),
|
||||
};
|
||||
|
||||
assert!(!record.clone().convert_ipv4_mapped());
|
||||
assert_eq!(record.into_ipv4_mapped().address, IpAddr::from(v4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_noderecord_codec_ipv4() {
|
||||
let mut rng = thread_rng();
|
||||
for _ in 0..100 {
|
||||
let mut ip = [0u8; 4];
|
||||
rng.fill_bytes(&mut ip);
|
||||
let record = NodeRecord {
|
||||
address: IpAddr::V4(ip.into()),
|
||||
tcp_port: rng.gen(),
|
||||
udp_port: rng.gen(),
|
||||
id: rng.gen(),
|
||||
};
|
||||
|
||||
let decoded = NodeRecord::decode(&mut alloy_rlp::encode(record).as_slice()).unwrap();
|
||||
assert_eq!(record, decoded);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_noderecord_codec_ipv6() {
|
||||
let mut rng = thread_rng();
|
||||
for _ in 0..100 {
|
||||
let mut ip = [0u8; 16];
|
||||
rng.fill_bytes(&mut ip);
|
||||
let record = NodeRecord {
|
||||
address: IpAddr::V6(ip.into()),
|
||||
tcp_port: rng.gen(),
|
||||
udp_port: rng.gen(),
|
||||
id: rng.gen(),
|
||||
};
|
||||
|
||||
let decoded = NodeRecord::decode(&mut alloy_rlp::encode(record).as_slice()).unwrap();
|
||||
assert_eq!(record, decoded);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_url_parse() {
|
||||
let url = "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301";
|
||||
let node: NodeRecord = url.parse().unwrap();
|
||||
assert_eq!(node, NodeRecord {
|
||||
address: IpAddr::V4([10,3,58,6].into()),
|
||||
tcp_port: 30303,
|
||||
udp_port: 30301,
|
||||
id: "6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0".parse().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_display() {
|
||||
let url = "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303";
|
||||
let node: NodeRecord = url.parse().unwrap();
|
||||
assert_eq!(url, &format!("{node}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_display_discport() {
|
||||
let url = "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301";
|
||||
let node: NodeRecord = url.parse().unwrap();
|
||||
assert_eq!(url, &format!("{node}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_serialize() {
|
||||
let node = NodeRecord{
|
||||
address: IpAddr::V4([10, 3, 58, 6].into()),
|
||||
tcp_port: 30303u16,
|
||||
udp_port: 30301u16,
|
||||
id: "6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0".parse().unwrap(),
|
||||
};
|
||||
let ser = serde_json::to_string::<NodeRecord>(&node).expect("couldn't serialize");
|
||||
assert_eq!(ser, "\"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301\"")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_node_deserialize() {
|
||||
let url = "\"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@10.3.58.6:30303?discport=30301\"";
|
||||
let node: NodeRecord = serde_json::from_str(url).expect("couldn't deserialize");
|
||||
assert_eq!(node, NodeRecord{
|
||||
address: IpAddr::V4([10, 3, 58, 6].into()),
|
||||
tcp_port: 30303u16,
|
||||
udp_port: 30301u16,
|
||||
id: "6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0".parse().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
3483
crates/chainspec/src/spec.rs
Normal file
3483
crates/chainspec/src/spec.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user