diff --git a/src/chainspec/hl.rs b/src/chainspec/hl.rs index 146e19d1f..a7dbb4f11 100644 --- a/src/chainspec/hl.rs +++ b/src/chainspec/hl.rs @@ -34,12 +34,10 @@ pub static HL_HARDFORKS: LazyLock = LazyLock::new(|| { ]) }); -/// The Hyperliqiud Mainnet spec -pub fn hl_mainnet() -> ChainSpec { +pub fn hl_chainspec(chain: Chain, genesis: &'static str) -> ChainSpec { ChainSpec { - chain: Chain::from_named(NamedChain::Hyperliquid), - genesis: serde_json::from_str(include_str!("genesis.json")) - .expect("Can't deserialize Hyperliquid Mainnet genesis json"), + chain, + genesis: serde_json::from_str(genesis).expect("Can't deserialize Hyperliquid genesis json"), genesis_header: empty_genesis_header(), paris_block_and_final_difficulty: Some((0, U256::from(0))), hardforks: HL_HARDFORKS.clone(), @@ -48,6 +46,18 @@ pub fn hl_mainnet() -> ChainSpec { } } +/// The Hyperliqiud Mainnet spec +pub fn hl_mainnet() -> ChainSpec { + hl_chainspec(Chain::from_named(NamedChain::Hyperliquid), include_str!("genesis.json")) +} + +/// The Hyperliqiud Testnet spec +pub fn hl_testnet() -> ChainSpec { + // Note: Testnet sync starts from snapshotted state [1] instead of genesis block. + // So the `alloc` field is not used, which makes it fine to reuse mainnet genesis file. + hl_chainspec(Chain::from_id_unchecked(998), include_str!("genesis.json")) +} + /// Empty genesis header for Hyperliquid Mainnet. /// /// The exact value is not known per se, but the parent hash of block 1 is known to be diff --git a/src/chainspec/parser.rs b/src/chainspec/parser.rs index d7fa4fcc8..610e5f212 100644 --- a/src/chainspec/parser.rs +++ b/src/chainspec/parser.rs @@ -1,11 +1,11 @@ -use crate::chainspec::HlChainSpec; +use crate::chainspec::{hl::hl_testnet, HlChainSpec}; use super::hl::hl_mainnet; use reth_cli::chainspec::ChainSpecParser; use std::sync::Arc; /// Chains supported by HyperEVM. First value should be used as the default. -pub const SUPPORTED_CHAINS: &[&str] = &["mainnet"]; +pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "testnet"]; /// Hyperliquid chain specification parser. #[derive(Debug, Clone, Default)] @@ -27,6 +27,7 @@ impl ChainSpecParser for HlChainSpecParser { pub fn chain_value_parser(s: &str) -> eyre::Result> { match s { "mainnet" => Ok(Arc::new(HlChainSpec { inner: hl_mainnet() })), + "testnet" => Ok(Arc::new(HlChainSpec { inner: hl_testnet() })), _ => Err(eyre::eyre!("Unsupported chain: {}", s)), } } diff --git a/src/pseudo_peer/mod.rs b/src/pseudo_peer/mod.rs index 991508b11..9dba0f3e5 100644 --- a/src/pseudo_peer/mod.rs +++ b/src/pseudo_peer/mod.rs @@ -50,6 +50,7 @@ pub async fn start_pseudo_peer( // Create network manager let (mut network, start_tx) = create_network_manager::( + (*chain_spec).clone(), destination_peer, block_source.clone(), blockhash_cache.clone(), diff --git a/src/pseudo_peer/network.rs b/src/pseudo_peer/network.rs index 98e0efdf1..dda503353 100644 --- a/src/pseudo_peer/network.rs +++ b/src/pseudo_peer/network.rs @@ -19,6 +19,7 @@ pub struct NetworkBuilder { boot_nodes: Vec, discovery_port: u16, listener_port: u16, + chain_spec: HlChainSpec, } impl Default for NetworkBuilder { @@ -29,6 +30,7 @@ impl Default for NetworkBuilder { boot_nodes: vec![], discovery_port: 0, listener_port: 0, + chain_spec: HlChainSpec::default(), } } } @@ -55,6 +57,11 @@ impl NetworkBuilder { self } + pub fn with_chain_spec(mut self, chain_spec: HlChainSpec) -> Self { + self.chain_spec = chain_spec; + self + } + pub async fn build( self, block_source: Arc>, @@ -80,12 +87,14 @@ impl NetworkBuilder { } pub async fn create_network_manager( + chain_spec: HlChainSpec, destination_peer: String, block_source: Arc>, blockhash_cache: BlockHashCache, ) -> eyre::Result<(NetworkManager, mpsc::Sender<()>)> { NetworkBuilder::default() .with_boot_nodes(vec![TrustedPeer::from_str(&destination_peer).unwrap()]) + .with_chain_spec(chain_spec) .build::(block_source, blockhash_cache) .await }