mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore(op): Add OpChainSpec (#10516)
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -6568,7 +6568,6 @@ version = "1.0.5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"eyre",
|
"eyre",
|
||||||
"reth-chainspec",
|
|
||||||
"reth-cli-runner",
|
"reth-cli-runner",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -7344,6 +7343,7 @@ dependencies = [
|
|||||||
"reth-evm",
|
"reth-evm",
|
||||||
"reth-execution-errors",
|
"reth-execution-errors",
|
||||||
"reth-execution-types",
|
"reth-execution-types",
|
||||||
|
"reth-optimism-chainspec",
|
||||||
"reth-optimism-consensus",
|
"reth-optimism-consensus",
|
||||||
"reth-primitives",
|
"reth-primitives",
|
||||||
"reth-prune-types",
|
"reth-prune-types",
|
||||||
@ -7971,6 +7971,7 @@ dependencies = [
|
|||||||
"alloy-chains",
|
"alloy-chains",
|
||||||
"alloy-genesis",
|
"alloy-genesis",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
|
"derive_more 1.0.0",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"op-alloy-rpc-types",
|
"op-alloy-rpc-types",
|
||||||
"reth-chainspec",
|
"reth-chainspec",
|
||||||
@ -7983,7 +7984,6 @@ dependencies = [
|
|||||||
name = "reth-optimism-cli"
|
name = "reth-optimism-cli"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-genesis",
|
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
"alloy-rlp",
|
"alloy-rlp",
|
||||||
"clap",
|
"clap",
|
||||||
@ -8013,8 +8013,6 @@ dependencies = [
|
|||||||
"reth-stages-types",
|
"reth-stages-types",
|
||||||
"reth-static-file",
|
"reth-static-file",
|
||||||
"reth-static-file-types",
|
"reth-static-file-types",
|
||||||
"serde_json",
|
|
||||||
"shellexpand",
|
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
|||||||
@ -14,7 +14,6 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
# reth
|
# reth
|
||||||
reth-cli-runner.workspace = true
|
reth-cli-runner.workspace = true
|
||||||
reth-chainspec.workspace = true
|
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
use clap::builder::TypedValueParser;
|
|
||||||
use reth_chainspec::ChainSpec;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use clap::builder::TypedValueParser;
|
||||||
|
|
||||||
/// Trait for parsing chain specifications.
|
/// Trait for parsing chain specifications.
|
||||||
///
|
///
|
||||||
/// This trait extends [`clap::builder::TypedValueParser`] to provide a parser for chain
|
/// This trait extends [`clap::builder::TypedValueParser`] to provide a parser for chain
|
||||||
/// specifications. Implementers of this trait must provide a list of supported chains and a
|
/// specifications. Implementers of this trait must provide a list of supported chains and a
|
||||||
/// function to parse a given string into a [`ChainSpec`].
|
/// function to parse a given string into a chain spec.
|
||||||
pub trait ChainSpecParser: TypedValueParser<Value = Arc<ChainSpec>> + Default {
|
pub trait ChainSpecParser<ChainSpec>: TypedValueParser<Value = Arc<ChainSpec>> + Default {
|
||||||
/// List of supported chains.
|
/// List of supported chains.
|
||||||
const SUPPORTED_CHAINS: &'static [&'static str];
|
const SUPPORTED_CHAINS: &'static [&'static str];
|
||||||
|
|
||||||
/// Parses the given string into a [`ChainSpec`].
|
/// Parses the given string into a chain spec.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
@ -20,6 +20,6 @@ pub trait ChainSpecParser: TypedValueParser<Value = Arc<ChainSpec>> + Default {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// This function will return an error if the input string cannot be parsed into a valid
|
/// This function will return an error if the input string cannot be parsed into a valid
|
||||||
/// [`ChainSpec`].
|
/// chain spec.
|
||||||
fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>>;
|
fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
|
|||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct EthChainSpecParser;
|
pub struct EthChainSpecParser;
|
||||||
|
|
||||||
impl ChainSpecParser for EthChainSpecParser {
|
impl ChainSpecParser<ChainSpec> for EthChainSpecParser {
|
||||||
const SUPPORTED_CHAINS: &'static [&'static str] = &["mainnet", "sepolia", "holesky", "dev"];
|
const SUPPORTED_CHAINS: &'static [&'static str] = &["mainnet", "sepolia", "holesky", "dev"];
|
||||||
|
|
||||||
fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
|
fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
|
||||||
@ -59,7 +59,7 @@ impl TypedValueParser for EthChainSpecParser {
|
|||||||
) -> Result<Self::Value, clap::Error> {
|
) -> Result<Self::Value, clap::Error> {
|
||||||
let val =
|
let val =
|
||||||
value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
|
value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
|
||||||
<Self as ChainSpecParser>::parse(val).map_err(|err| {
|
<Self as ChainSpecParser<ChainSpec>>::parse(val).map_err(|err| {
|
||||||
let arg = arg.map(|a| a.to_string()).unwrap_or_else(|| "...".to_owned());
|
let arg = arg.map(|a| a.to_string()).unwrap_or_else(|| "...".to_owned());
|
||||||
let possible_values = Self::SUPPORTED_CHAINS.join(",");
|
let possible_values = Self::SUPPORTED_CHAINS.join(",");
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
@ -84,7 +84,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn parse_known_chain_spec() {
|
fn parse_known_chain_spec() {
|
||||||
for &chain in EthChainSpecParser::SUPPORTED_CHAINS {
|
for &chain in EthChainSpecParser::SUPPORTED_CHAINS {
|
||||||
assert!(<EthChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
|
assert!(<EthChainSpecParser as ChainSpecParser<ChainSpec>>::parse(chain).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@ reth-network-peers.workspace = true
|
|||||||
reth-consensus-common.workspace = true
|
reth-consensus-common.workspace = true
|
||||||
reth-prune-types.workspace = true
|
reth-prune-types.workspace = true
|
||||||
reth-stages-types.workspace = true
|
reth-stages-types.workspace = true
|
||||||
reth-optimism-chainspec = { workspace = true, features = ["optimism"], optional = true }
|
reth-optimism-chainspec = { workspace = true, optional = true }
|
||||||
|
|
||||||
# ethereum
|
# ethereum
|
||||||
alloy-genesis.workspace = true
|
alloy-genesis.workspace = true
|
||||||
|
|||||||
@ -3,16 +3,17 @@
|
|||||||
use std::{path::PathBuf, sync::Arc};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use alloy_genesis::Genesis;
|
use alloy_genesis::Genesis;
|
||||||
use reth_chainspec::{ChainSpec, DEV};
|
use reth_chainspec::ChainSpec;
|
||||||
#[cfg(not(feature = "optimism"))]
|
#[cfg(not(feature = "optimism"))]
|
||||||
use reth_chainspec::{HOLESKY, MAINNET, SEPOLIA};
|
use reth_chainspec::{DEV, HOLESKY, MAINNET, SEPOLIA};
|
||||||
use reth_fs_util as fs;
|
use reth_fs_util as fs;
|
||||||
#[cfg(feature = "optimism")]
|
#[cfg(feature = "optimism")]
|
||||||
use reth_optimism_chainspec::{BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA};
|
use reth_optimism_chainspec::{BASE_MAINNET, BASE_SEPOLIA, OP_DEV, OP_MAINNET, OP_SEPOLIA};
|
||||||
|
|
||||||
#[cfg(feature = "optimism")]
|
#[cfg(feature = "optimism")]
|
||||||
/// Chains supported by op-reth. First value should be used as the default.
|
/// Chains supported by op-reth. First value should be used as the default.
|
||||||
pub const SUPPORTED_CHAINS: &[&str] = &["optimism", "optimism-sepolia", "base", "base-sepolia"];
|
pub const SUPPORTED_CHAINS: &[&str] =
|
||||||
|
&["optimism", "optimism-sepolia", "base", "base-sepolia", "dev"];
|
||||||
#[cfg(not(feature = "optimism"))]
|
#[cfg(not(feature = "optimism"))]
|
||||||
/// Chains supported by reth. First value should be used as the default.
|
/// Chains supported by reth. First value should be used as the default.
|
||||||
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "dev"];
|
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "dev"];
|
||||||
@ -26,24 +27,35 @@ pub fn chain_help() -> String {
|
|||||||
///
|
///
|
||||||
/// The value parser matches either a known chain, the path
|
/// The value parser matches either a known chain, the path
|
||||||
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
|
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
|
||||||
|
#[cfg(not(feature = "optimism"))]
|
||||||
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
|
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
|
||||||
Ok(match s {
|
Ok(match s {
|
||||||
#[cfg(not(feature = "optimism"))]
|
|
||||||
"mainnet" => MAINNET.clone(),
|
"mainnet" => MAINNET.clone(),
|
||||||
#[cfg(not(feature = "optimism"))]
|
|
||||||
"sepolia" => SEPOLIA.clone(),
|
"sepolia" => SEPOLIA.clone(),
|
||||||
#[cfg(not(feature = "optimism"))]
|
|
||||||
"holesky" => HOLESKY.clone(),
|
"holesky" => HOLESKY.clone(),
|
||||||
"dev" => DEV.clone(),
|
"dev" => DEV.clone(),
|
||||||
#[cfg(feature = "optimism")]
|
_ => Arc::new(parse_custom_chain_spec(s)?),
|
||||||
"optimism" => OP_MAINNET.clone(),
|
})
|
||||||
#[cfg(feature = "optimism")]
|
}
|
||||||
"optimism_sepolia" | "optimism-sepolia" => OP_SEPOLIA.clone(),
|
|
||||||
#[cfg(feature = "optimism")]
|
/// Clap value parser for [`OpChainSpec`](reth_optimism_chainspec::OpChainSpec)s.
|
||||||
"base" => BASE_MAINNET.clone(),
|
///
|
||||||
#[cfg(feature = "optimism")]
|
/// The value parser matches either a known chain, the path
|
||||||
"base_sepolia" | "base-sepolia" => BASE_SEPOLIA.clone(),
|
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
|
||||||
_ => {
|
#[cfg(feature = "optimism")]
|
||||||
|
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
|
||||||
|
Ok(Arc::new(match s {
|
||||||
|
"optimism" => OP_MAINNET.inner.clone(),
|
||||||
|
"optimism_sepolia" | "optimism-sepolia" => OP_SEPOLIA.inner.clone(),
|
||||||
|
"base" => BASE_MAINNET.inner.clone(),
|
||||||
|
"base_sepolia" | "base-sepolia" => BASE_SEPOLIA.inner.clone(),
|
||||||
|
"dev" => OP_DEV.inner.clone(),
|
||||||
|
_ => parse_custom_chain_spec(s)?,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses a custom [`ChainSpec`].
|
||||||
|
pub fn parse_custom_chain_spec(s: &str) -> eyre::Result<ChainSpec, eyre::Error> {
|
||||||
// try to read json from path first
|
// try to read json from path first
|
||||||
let raw = match fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned())) {
|
let raw = match fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned())) {
|
||||||
Ok(raw) => raw,
|
Ok(raw) => raw,
|
||||||
@ -60,9 +72,7 @@ pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error>
|
|||||||
// both serialized Genesis and ChainSpec structs supported
|
// both serialized Genesis and ChainSpec structs supported
|
||||||
let genesis: Genesis = serde_json::from_str(&raw)?;
|
let genesis: Genesis = serde_json::from_str(&raw)?;
|
||||||
|
|
||||||
Arc::new(genesis.into())
|
Ok(genesis.into())
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -26,6 +26,7 @@ serde_json.workspace = true
|
|||||||
|
|
||||||
# misc
|
# misc
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
|
derive_more.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
reth-chainspec = { workspace = true, features = ["test-utils"] }
|
reth-chainspec = { workspace = true, features = ["test-utils"] }
|
||||||
@ -35,4 +36,3 @@ op-alloy-rpc-types.workspace = true
|
|||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
optimism = []
|
|
||||||
1
crates/optimism/chainspec/res/genesis/dev.json
Normal file
1
crates/optimism/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"}
|
||||||
@ -11,9 +11,12 @@ use once_cell::sync::Lazy;
|
|||||||
use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
||||||
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
||||||
|
|
||||||
|
use crate::OpChainSpec;
|
||||||
|
|
||||||
/// The Base mainnet spec
|
/// The Base mainnet spec
|
||||||
pub static BASE_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
pub static BASE_MAINNET: Lazy<Arc<OpChainSpec>> = Lazy::new(|| {
|
||||||
ChainSpec {
|
OpChainSpec {
|
||||||
|
inner: ChainSpec {
|
||||||
chain: Chain::base_mainnet(),
|
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"),
|
.expect("Can't deserialize Base genesis json"),
|
||||||
@ -32,6 +35,7 @@ pub static BASE_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
|||||||
max_gas_limit: crate::constants::BASE_MAINNET_MAX_GAS_LIMIT,
|
max_gas_limit: crate::constants::BASE_MAINNET_MAX_GAS_LIMIT,
|
||||||
prune_delete_limit: 10000,
|
prune_delete_limit: 10000,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
|||||||
@ -11,9 +11,12 @@ use once_cell::sync::Lazy;
|
|||||||
use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
||||||
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
||||||
|
|
||||||
|
use crate::OpChainSpec;
|
||||||
|
|
||||||
/// The Base Sepolia spec
|
/// The Base Sepolia spec
|
||||||
pub static BASE_SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
pub static BASE_SEPOLIA: Lazy<Arc<OpChainSpec>> = Lazy::new(|| {
|
||||||
ChainSpec {
|
OpChainSpec {
|
||||||
|
inner: ChainSpec {
|
||||||
chain: Chain::base_sepolia(),
|
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"),
|
.expect("Can't deserialize Base Sepolia genesis json"),
|
||||||
@ -32,6 +35,7 @@ pub static BASE_SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
|||||||
max_gas_limit: crate::constants::BASE_SEPOLIA_MAX_GAS_LIMIT,
|
max_gas_limit: crate::constants::BASE_SEPOLIA_MAX_GAS_LIMIT,
|
||||||
prune_delete_limit: 10000,
|
prune_delete_limit: 10000,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
|||||||
38
crates/optimism/chainspec/src/dev.rs
Normal file
38
crates/optimism/chainspec/src/dev.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//! Chain specification in dev mode for custom chain.
|
||||||
|
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use alloy_chains::Chain;
|
||||||
|
use alloy_primitives::U256;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
||||||
|
use reth_ethereum_forks::DEV_HARDFORKS;
|
||||||
|
use reth_primitives_traits::constants::DEV_GENESIS_HASH;
|
||||||
|
|
||||||
|
use crate::OpChainSpec;
|
||||||
|
|
||||||
|
/// OP dev testnet specification
|
||||||
|
///
|
||||||
|
/// Includes 20 prefunded accounts with `10_000` ETH each derived from mnemonic "test test test test
|
||||||
|
/// test test test test test test test junk".
|
||||||
|
pub static OP_DEV: Lazy<Arc<OpChainSpec>> = Lazy::new(|| {
|
||||||
|
{
|
||||||
|
OpChainSpec {
|
||||||
|
inner: ChainSpec {
|
||||||
|
chain: Chain::dev(),
|
||||||
|
genesis: serde_json::from_str(include_str!("../res/genesis/dev.json"))
|
||||||
|
.expect("Can't deserialize Dev testnet genesis json"),
|
||||||
|
genesis_hash: Some(DEV_GENESIS_HASH),
|
||||||
|
paris_block_and_final_difficulty: Some((0, U256::from(0))),
|
||||||
|
hardforks: DEV_HARDFORKS.clone(),
|
||||||
|
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||||
|
deposit_contract: None, // TODO: do we even have?
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
});
|
||||||
@ -5,10 +5,7 @@
|
|||||||
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
|
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
|
||||||
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
|
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(all(not(test), feature = "optimism"), warn(unused_crate_dependencies))]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||||
// The `optimism` feature must be enabled to use this crate.
|
|
||||||
#![cfg(feature = "optimism")]
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
@ -17,14 +14,26 @@ pub mod constants;
|
|||||||
|
|
||||||
mod base;
|
mod base;
|
||||||
mod base_sepolia;
|
mod base_sepolia;
|
||||||
|
mod dev;
|
||||||
mod op;
|
mod op;
|
||||||
mod op_sepolia;
|
mod op_sepolia;
|
||||||
|
|
||||||
pub use base::BASE_MAINNET;
|
pub use base::BASE_MAINNET;
|
||||||
pub use base_sepolia::BASE_SEPOLIA;
|
pub use base_sepolia::BASE_SEPOLIA;
|
||||||
|
pub use dev::OP_DEV;
|
||||||
pub use op::OP_MAINNET;
|
pub use op::OP_MAINNET;
|
||||||
pub use op_sepolia::OP_SEPOLIA;
|
pub use op_sepolia::OP_SEPOLIA;
|
||||||
|
|
||||||
|
use derive_more::{Constructor, Deref, Into};
|
||||||
|
use reth_chainspec::ChainSpec;
|
||||||
|
|
||||||
|
/// OP stack chain spec type.
|
||||||
|
#[derive(Debug, Deref, Into, Constructor)]
|
||||||
|
pub struct OpChainSpec {
|
||||||
|
/// [`ChainSpec`].
|
||||||
|
pub inner: ChainSpec,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use alloy_genesis::Genesis;
|
use alloy_genesis::Genesis;
|
||||||
|
|||||||
@ -12,9 +12,12 @@ use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
|||||||
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
||||||
use reth_primitives_traits::constants::ETHEREUM_BLOCK_GAS_LIMIT;
|
use reth_primitives_traits::constants::ETHEREUM_BLOCK_GAS_LIMIT;
|
||||||
|
|
||||||
|
use crate::OpChainSpec;
|
||||||
|
|
||||||
/// The Optimism Mainnet spec
|
/// The Optimism Mainnet spec
|
||||||
pub static OP_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
pub static OP_MAINNET: Lazy<Arc<OpChainSpec>> = Lazy::new(|| {
|
||||||
ChainSpec {
|
OpChainSpec {
|
||||||
|
inner: ChainSpec {
|
||||||
chain: Chain::optimism_mainnet(),
|
chain: Chain::optimism_mainnet(),
|
||||||
// genesis contains empty alloc field because state at first bedrock block is imported
|
// genesis contains empty alloc field because state at first bedrock block is imported
|
||||||
// manually from trusted source
|
// manually from trusted source
|
||||||
@ -35,6 +38,7 @@ pub static OP_MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
|||||||
max_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT,
|
max_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT,
|
||||||
prune_delete_limit: 10000,
|
prune_delete_limit: 10000,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
|||||||
@ -12,9 +12,12 @@ use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
|
|||||||
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
use reth_ethereum_forks::{EthereumHardfork, OptimismHardfork};
|
||||||
use reth_primitives_traits::constants::ETHEREUM_BLOCK_GAS_LIMIT;
|
use reth_primitives_traits::constants::ETHEREUM_BLOCK_GAS_LIMIT;
|
||||||
|
|
||||||
|
use crate::OpChainSpec;
|
||||||
|
|
||||||
/// The OP Sepolia spec
|
/// The OP Sepolia spec
|
||||||
pub static OP_SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
pub static OP_SEPOLIA: Lazy<Arc<OpChainSpec>> = Lazy::new(|| {
|
||||||
ChainSpec {
|
OpChainSpec {
|
||||||
|
inner: ChainSpec {
|
||||||
chain: Chain::from_named(NamedChain::OptimismSepolia),
|
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"),
|
.expect("Can't deserialize OP Sepolia genesis json"),
|
||||||
@ -33,6 +36,7 @@ pub static OP_SEPOLIA: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
|
|||||||
max_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT,
|
max_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT,
|
||||||
prune_delete_limit: 10000,
|
prune_delete_limit: 10000,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
|||||||
@ -27,7 +27,7 @@ reth-primitives.workspace = true
|
|||||||
|
|
||||||
## optimisim
|
## optimisim
|
||||||
reth-optimism-primitives.workspace = true
|
reth-optimism-primitives.workspace = true
|
||||||
reth-optimism-chainspec = { workspace = true, features = ["optimism"] }
|
reth-optimism-chainspec.workspace = true
|
||||||
|
|
||||||
reth-chainspec.workspace = true
|
reth-chainspec.workspace = true
|
||||||
reth-stages-types.workspace = true
|
reth-stages-types.workspace = true
|
||||||
@ -39,14 +39,11 @@ reth-evm-optimism.workspace = true
|
|||||||
reth-cli.workspace = true
|
reth-cli.workspace = true
|
||||||
|
|
||||||
# eth
|
# eth
|
||||||
alloy-genesis.workspace = true
|
|
||||||
alloy-primitives.workspace = true
|
alloy-primitives.workspace = true
|
||||||
alloy-rlp.workspace = true
|
alloy-rlp.workspace = true
|
||||||
|
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
shellexpand.workspace = true
|
|
||||||
serde_json.workspace = true
|
|
||||||
futures-util.workspace = true
|
futures-util.workspace = true
|
||||||
clap = { workspace = true, features = ["derive", "env"] }
|
clap = { workspace = true, features = ["derive", "env"] }
|
||||||
|
|
||||||
|
|||||||
@ -1,41 +1,24 @@
|
|||||||
use std::{ffi::OsStr, fs, path::PathBuf, sync::Arc};
|
use std::{ffi::OsStr, sync::Arc};
|
||||||
|
|
||||||
use alloy_genesis::Genesis;
|
|
||||||
use clap::{builder::TypedValueParser, error::Result, Arg, Command};
|
use clap::{builder::TypedValueParser, error::Result, Arg, Command};
|
||||||
use reth_chainspec::{ChainSpec, DEV};
|
|
||||||
use reth_cli::chainspec::ChainSpecParser;
|
use reth_cli::chainspec::ChainSpecParser;
|
||||||
use reth_optimism_chainspec::{BASE_MAINNET, BASE_SEPOLIA, OP_MAINNET, OP_SEPOLIA};
|
use reth_node_core::args::utils::parse_custom_chain_spec;
|
||||||
|
use reth_optimism_chainspec::{
|
||||||
|
OpChainSpec, BASE_MAINNET, BASE_SEPOLIA, OP_DEV, OP_MAINNET, OP_SEPOLIA,
|
||||||
|
};
|
||||||
|
|
||||||
/// Clap value parser for [`ChainSpec`]s.
|
/// Clap value parser for [`OpChainSpec`]s.
|
||||||
///
|
///
|
||||||
/// The value parser matches either a known chain, the path
|
/// The value parser matches either a known chain, the path
|
||||||
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
|
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
|
||||||
fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
|
fn chain_value_parser(s: &str) -> eyre::Result<Arc<OpChainSpec>, eyre::Error> {
|
||||||
Ok(match s {
|
Ok(match s {
|
||||||
"dev" => DEV.clone(),
|
"dev" => OP_DEV.clone(),
|
||||||
"optimism" => OP_MAINNET.clone(),
|
"optimism" => OP_MAINNET.clone(),
|
||||||
"optimism_sepolia" | "optimism-sepolia" => OP_SEPOLIA.clone(),
|
"optimism_sepolia" | "optimism-sepolia" => OP_SEPOLIA.clone(),
|
||||||
"base" => BASE_MAINNET.clone(),
|
"base" => BASE_MAINNET.clone(),
|
||||||
"base_sepolia" | "base-sepolia" => BASE_SEPOLIA.clone(),
|
"base_sepolia" | "base-sepolia" => BASE_SEPOLIA.clone(),
|
||||||
_ => {
|
_ => Arc::new(OpChainSpec { inner: parse_custom_chain_spec(s)? }),
|
||||||
// try to read json from path first
|
|
||||||
let raw = match fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned())) {
|
|
||||||
Ok(raw) => raw,
|
|
||||||
Err(io_err) => {
|
|
||||||
// valid json may start with "\n", but must contain "{"
|
|
||||||
if s.contains('{') {
|
|
||||||
s.to_string()
|
|
||||||
} else {
|
|
||||||
return Err(io_err.into()) // assume invalid path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// both serialized Genesis and ChainSpec structs supported
|
|
||||||
let genesis: Genesis = serde_json::from_str(&raw)?;
|
|
||||||
|
|
||||||
Arc::new(genesis.into())
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,8 +26,9 @@ fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
|
|||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct OpChainSpecParser;
|
pub struct OpChainSpecParser;
|
||||||
|
|
||||||
impl ChainSpecParser for OpChainSpecParser {
|
impl ChainSpecParser<OpChainSpec> for OpChainSpecParser {
|
||||||
const SUPPORTED_CHAINS: &'static [&'static str] = &[
|
const SUPPORTED_CHAINS: &'static [&'static str] = &[
|
||||||
|
"dev",
|
||||||
"optimism",
|
"optimism",
|
||||||
"optimism_sepolia",
|
"optimism_sepolia",
|
||||||
"optimism-sepolia",
|
"optimism-sepolia",
|
||||||
@ -53,13 +37,13 @@ impl ChainSpecParser for OpChainSpecParser {
|
|||||||
"base-sepolia",
|
"base-sepolia",
|
||||||
];
|
];
|
||||||
|
|
||||||
fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
|
fn parse(s: &str) -> eyre::Result<Arc<OpChainSpec>> {
|
||||||
chain_value_parser(s)
|
chain_value_parser(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypedValueParser for OpChainSpecParser {
|
impl TypedValueParser for OpChainSpecParser {
|
||||||
type Value = Arc<ChainSpec>;
|
type Value = Arc<OpChainSpec>;
|
||||||
|
|
||||||
fn parse_ref(
|
fn parse_ref(
|
||||||
&self,
|
&self,
|
||||||
@ -69,7 +53,7 @@ impl TypedValueParser for OpChainSpecParser {
|
|||||||
) -> Result<Self::Value, clap::Error> {
|
) -> Result<Self::Value, clap::Error> {
|
||||||
let val =
|
let val =
|
||||||
value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
|
value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;
|
||||||
<Self as ChainSpecParser>::parse(val).map_err(|err| {
|
<Self as ChainSpecParser<OpChainSpec>>::parse(val).map_err(|err| {
|
||||||
let arg = arg.map(|a| a.to_string()).unwrap_or_else(|| "...".to_owned());
|
let arg = arg.map(|a| a.to_string()).unwrap_or_else(|| "...".to_owned());
|
||||||
let possible_values = Self::SUPPORTED_CHAINS.join(", ");
|
let possible_values = Self::SUPPORTED_CHAINS.join(", ");
|
||||||
clap::Error::raw(
|
clap::Error::raw(
|
||||||
@ -96,7 +80,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn parse_known_chain_spec() {
|
fn parse_known_chain_spec() {
|
||||||
for &chain in OpChainSpecParser::SUPPORTED_CHAINS {
|
for &chain in OpChainSpecParser::SUPPORTED_CHAINS {
|
||||||
assert!(<OpChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
|
assert!(<OpChainSpecParser as ChainSpecParser<OpChainSpec>>::parse(chain).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ tracing.workspace = true
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
reth-revm = { workspace = true, features = ["test-utils"] }
|
reth-revm = { workspace = true, features = ["test-utils"] }
|
||||||
|
reth-optimism-chainspec.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
optimism = [
|
optimism = [
|
||||||
|
|||||||
@ -501,8 +501,11 @@ mod tests {
|
|||||||
let account = Account { balance: U256::MAX, ..Account::default() };
|
let account = Account { balance: U256::MAX, ..Account::default() };
|
||||||
db.insert_account(addr, account, None, HashMap::new());
|
db.insert_account(addr, account, None, HashMap::new());
|
||||||
|
|
||||||
let chain_spec =
|
let chain_spec = Arc::new(
|
||||||
Arc::new(ChainSpecBuilder::from(&*BASE_MAINNET).regolith_activated().build());
|
ChainSpecBuilder::from(&Arc::new(BASE_MAINNET.inner.clone()))
|
||||||
|
.regolith_activated()
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
|
|
||||||
let tx = TransactionSigned::from_transaction_and_signature(
|
let tx = TransactionSigned::from_transaction_and_signature(
|
||||||
Transaction::Eip1559(TxEip1559 {
|
Transaction::Eip1559(TxEip1559 {
|
||||||
@ -582,8 +585,11 @@ mod tests {
|
|||||||
|
|
||||||
db.insert_account(addr, account, None, HashMap::new());
|
db.insert_account(addr, account, None, HashMap::new());
|
||||||
|
|
||||||
let chain_spec =
|
let chain_spec = Arc::new(
|
||||||
Arc::new(ChainSpecBuilder::from(&*BASE_MAINNET).canyon_activated().build());
|
ChainSpecBuilder::from(&Arc::new(BASE_MAINNET.inner.clone()))
|
||||||
|
.canyon_activated()
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
|
|
||||||
let tx = TransactionSigned::from_transaction_and_signature(
|
let tx = TransactionSigned::from_transaction_and_signature(
|
||||||
Transaction::Eip1559(TxEip1559 {
|
Transaction::Eip1559(TxEip1559 {
|
||||||
|
|||||||
@ -37,7 +37,7 @@ reth-rpc-eth-types.workspace = true
|
|||||||
reth-rpc-eth-api.workspace = true
|
reth-rpc-eth-api.workspace = true
|
||||||
reth-optimism-rpc.workspace = true
|
reth-optimism-rpc.workspace = true
|
||||||
reth-rpc.workspace = true
|
reth-rpc.workspace = true
|
||||||
reth-optimism-chainspec = { workspace = true, features = ["optimism"] }
|
reth-optimism-chainspec.workspace = true
|
||||||
|
|
||||||
# async
|
# async
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
|
|||||||
@ -20,7 +20,7 @@ reth-trie-common.workspace = true
|
|||||||
revm-primitives = { workspace = true, features = ["serde"] }
|
revm-primitives = { workspace = true, features = ["serde"] }
|
||||||
reth-chainspec = { workspace = true, optional = true }
|
reth-chainspec = { workspace = true, optional = true }
|
||||||
reth-codecs = { workspace = true, optional = true }
|
reth-codecs = { workspace = true, optional = true }
|
||||||
reth-optimism-chainspec = { workspace = true, optional = true, features = ["optimism"] }
|
reth-optimism-chainspec = { workspace = true, optional = true }
|
||||||
|
|
||||||
# ethereum
|
# ethereum
|
||||||
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
|
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
|
||||||
|
|||||||
Reference in New Issue
Block a user