diff --git a/Cargo.lock b/Cargo.lock index 54f93a6e4..f9e71299c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -966,6 +966,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" + [[package]] name = "bit-set" version = "0.5.3" @@ -2586,6 +2592,7 @@ dependencies = [ "alloy-rlp", "anyhow", "base64 0.13.1", + "bimap", "bytes 1.6.0", "c-kzg", "clap", @@ -2603,6 +2610,7 @@ dependencies = [ "keccak-hash", "lazy_static", "nanotemplate", + "once_cell", "quickcheck", "rand 0.8.5", "reth-rpc-types", diff --git a/ethportal-api/Cargo.toml b/ethportal-api/Cargo.toml index 1d5fa9622..2e6768cbf 100644 --- a/ethportal-api/Cargo.toml +++ b/ethportal-api/Cargo.toml @@ -15,6 +15,7 @@ alloy-primitives = { version = "0.7.0", features = ["ssz"] } alloy-rlp = "0.3.4" anyhow = "1.0.68" base64 = "0.13.0" +bimap = "0.6.3" bytes = "1.3.0" clap = { version = "4.2.1", features = ["derive"] } const_format = {version = "0.2.0", features = ["rust_1_64"]} @@ -31,6 +32,7 @@ jsonrpsee = {version="0.20.0", features = ["async-client", "client", "macros", " keccak-hash = "0.10.0" lazy_static = "1.4.0" nanotemplate = "0.3.0" +once_cell = "1.17" quickcheck = "1.0.3" rand = "0.8.5" reth-rpc-types = { rev = "8d1d13ef89cf19459adc37ba0c45e7aac6270dc1", git = "https://github.com/paradigmxyz/reth.git"} diff --git a/ethportal-api/src/types/cli.rs b/ethportal-api/src/types/cli.rs index fa0820c6d..850c20287 100644 --- a/ethportal-api/src/types/cli.rs +++ b/ethportal-api/src/types/cli.rs @@ -4,7 +4,7 @@ use clap::{ error::{Error, ErrorKind}, Args, Parser, Subcommand, }; -use std::{env, ffi::OsString, fmt, net::SocketAddr, path::PathBuf, str::FromStr}; +use std::{env, ffi::OsString, fmt, net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc}; use trin_utils::build_info; use url::Url; @@ -21,11 +21,14 @@ pub const BEACON_NETWORK: &str = "beacon"; pub const HISTORY_NETWORK: &str = "history"; pub const STATE_NETWORK: &str = "state"; const DEFAULT_SUBNETWORKS: &str = "history"; +pub const DEFAULT_NETWORK: &str = "mainnet"; pub const DEFAULT_STORAGE_CAPACITY_MB: &str = "100"; pub const DEFAULT_WEB3_TRANSPORT: &str = "ipc"; use crate::dashboard::grafana::{GrafanaAPI, DASHBOARD_TEMPLATES}; +use super::portal_wire::{NetworkSpec, MAINNET, TESTNET}; + #[derive(Debug, PartialEq, Clone)] pub enum Web3TransportType { HTTP, @@ -147,12 +150,20 @@ pub struct TrinConfig { pub trusted_block_root: Option, #[arg( - long = "networks", + long = "portal-subnetworks", help = "Comma-separated list of which portal subnetworks to activate", default_value = DEFAULT_SUBNETWORKS, use_value_delimiter = true )] - pub networks: Vec, + pub portal_subnetworks: Vec, + + #[arg( + long = "network", + help = "Choose mainnet or testnet", + default_value = DEFAULT_NETWORK, + value_parser = network_parser + )] + pub network: Arc, /// Storage capacity specified in megabytes. #[arg( @@ -225,7 +236,7 @@ impl Default for TrinConfig { no_upnp: false, private_key: None, trusted_block_root: None, - networks: DEFAULT_SUBNETWORKS + portal_subnetworks: DEFAULT_SUBNETWORKS .split(',') .map(|n| n.to_string()) .collect(), @@ -240,6 +251,7 @@ impl Default for TrinConfig { ws_port: DEFAULT_WEB3_WS_PORT, command: None, utp_transfer_limit: DEFAULT_UTP_TRANSFER_LIMIT, + network: MAINNET.clone(), } } } @@ -299,6 +311,16 @@ pub fn check_private_key_length(private_key: &str) -> Result { )) } +fn network_parser(network_string: &str) -> Result, String> { + match network_string { + "mainnet" => Ok(MAINNET.clone()), + "testnet" => Ok(TESTNET.clone()), + _ => Err(format!( + "Not a valid network: {network_string}, must be 'testnet' or 'mainnet'" + )), + } +} + fn check_trusted_block_root(trusted_root: &str) -> Result { if !trusted_root.starts_with("0x") { return Err("Trusted block root must be prefixed with 0x".to_owned()); @@ -324,7 +346,7 @@ impl fmt::Display for TrinConfig { write!( f, "TrinConfig {{ networks: {:?}, capacity_mb: {}, ephemeral: {}, json_rpc_url: {}, metrics_enabled: {} }}", - self.networks, self.mb, self.ephemeral, json_rpc_url, self.enable_metrics_with_url.is_some() + self.portal_subnetworks, self.mb, self.ephemeral, json_rpc_url, self.enable_metrics_with_url.is_some() ) } } diff --git a/ethportal-api/src/types/portal_wire.rs b/ethportal-api/src/types/portal_wire.rs index 7256acee0..d593c3b31 100644 --- a/ethportal-api/src/types/portal_wire.rs +++ b/ethportal-api/src/types/portal_wire.rs @@ -2,10 +2,12 @@ use std::{ convert::{TryFrom, TryInto}, fmt, ops::Deref, - str::FromStr, + sync::Arc, }; use alloy_primitives::U256; +use bimap::BiHashMap; +use once_cell::sync::Lazy; use rlp::Encodable; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; @@ -164,7 +166,7 @@ pub enum ProtocolIdError { } /// Protocol identifiers -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum ProtocolId { State, History, @@ -174,23 +176,65 @@ pub enum ProtocolId { Utp, } -/// Encode hex string to protocol id -impl FromStr for ProtocolId { - type Err = ProtocolIdError; +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct NetworkSpec { + network_name: String, + portal_networks: BiHashMap, +} - fn from_str(input: &str) -> Result { - match input { - "0x500A" => Ok(ProtocolId::State), - "0x500B" => Ok(ProtocolId::History), - "0x500C" => Ok(ProtocolId::TransactionGossip), - "0x500D" => Ok(ProtocolId::CanonicalIndices), - "0x501A" => Ok(ProtocolId::Beacon), - "0x757470" => Ok(ProtocolId::Utp), - _ => Err(ProtocolIdError::Invalid), - } +impl NetworkSpec { + pub fn get_network_name(&self) -> &str { + &self.network_name + } + + pub fn get_protocol_id_from_hex(&self, hex: &str) -> Result { + self.portal_networks + .get_by_right(hex) + .copied() + .ok_or(ProtocolIdError::Invalid) + } + + pub fn get_protocol_hex_from_id( + &self, + protocol_id: &ProtocolId, + ) -> Result { + self.portal_networks + .get_by_left(protocol_id) + .cloned() + .ok_or(ProtocolIdError::Invalid) } } +pub static MAINNET: Lazy> = Lazy::new(|| { + let mut portal_networks = BiHashMap::new(); + portal_networks.insert(ProtocolId::State, "0x500A".to_string()); + portal_networks.insert(ProtocolId::History, "0x500B".to_string()); + portal_networks.insert(ProtocolId::TransactionGossip, "0x500C".to_string()); + portal_networks.insert(ProtocolId::CanonicalIndices, "0x500D".to_string()); + portal_networks.insert(ProtocolId::Beacon, "0x501A".to_string()); + portal_networks.insert(ProtocolId::Utp, "0x757470".to_string()); + NetworkSpec { + portal_networks, + network_name: "mainnet".to_string(), + } + .into() +}); + +pub static TESTNET: Lazy> = Lazy::new(|| { + let mut portal_networks = BiHashMap::new(); + portal_networks.insert(ProtocolId::State, "0x501A".to_string()); + portal_networks.insert(ProtocolId::History, "0x501B".to_string()); + portal_networks.insert(ProtocolId::TransactionGossip, "0x501C".to_string()); + portal_networks.insert(ProtocolId::CanonicalIndices, "0x501D".to_string()); + portal_networks.insert(ProtocolId::Beacon, "0x502A".to_string()); + portal_networks.insert(ProtocolId::Utp, "0x757470".to_string()); + NetworkSpec { + portal_networks, + network_name: "testnet".to_string(), + } + .into() +}); + impl fmt::Display for ProtocolId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let protocol = match self { @@ -590,21 +634,20 @@ impl From for Value { #[allow(clippy::unwrap_used)] mod test { use super::*; - use crate::utils::bytes::hex_encode_upper; + use std::str::FromStr; use test_log::test; #[test] - #[should_panic] fn protocol_id_invalid() { let hex = "0x500F"; - ProtocolId::from_str(hex).unwrap(); + assert!(!MAINNET.portal_networks.contains_right(hex)); } #[test] fn protocol_id_encoding() { let hex = "0x500A"; - let protocol_id = ProtocolId::from_str(hex).unwrap(); - let expected_hex = hex_encode_upper(Vec::try_from(protocol_id).unwrap()); + let protocol_id = MAINNET.get_protocol_id_from_hex(hex).unwrap(); + let expected_hex = MAINNET.get_protocol_hex_from_id(&protocol_id).unwrap(); assert_eq!(hex, expected_hex); } diff --git a/ethportal-peertest/src/lib.rs b/ethportal-peertest/src/lib.rs index 8df6ef6cf..0b9baa34e 100644 --- a/ethportal-peertest/src/lib.rs +++ b/ethportal-peertest/src/lib.rs @@ -79,7 +79,7 @@ fn generate_trin_config(id: u16, bootnode_enr: Option<&Enr>) -> TrinConfig { let web3_ipc_path_str = web3_ipc_path.as_path().display().to_string(); let trin_config_args = vec![ "trin", - "--networks", + "--portal-subnetworks", "history,beacon,state", "--external-address", external_addr.as_str(), @@ -101,7 +101,7 @@ fn generate_trin_config(id: u16, bootnode_enr: Option<&Enr>) -> TrinConfig { let web3_ipc_path_str = web3_ipc_path.as_path().display().to_string(); let trin_config_args = vec![ "trin", - "--networks", + "--portal-subnetworks", "history,beacon,state", "--external-address", external_addr.as_str(), diff --git a/ethportal-peertest/src/scenarios/basic.rs b/ethportal-peertest/src/scenarios/basic.rs index 14f2e222d..f0203c9bc 100644 --- a/ethportal-peertest/src/scenarios/basic.rs +++ b/ethportal-peertest/src/scenarios/basic.rs @@ -133,6 +133,14 @@ pub async fn test_ping(protocol: ProtocolId, target: &Client, peertest: &Peertes assert_eq!(result.enr_seq, 1); } +pub async fn test_ping_cross_network(target: &Client, peertest: &Peertest) { + info!("Testing ping for history cross mainnet and testnet discv5 protocol id"); + let bootnode_enr = peertest.bootnode.enr.clone(); + if let Ok(pong) = HistoryNetworkApiClient::ping(target, bootnode_enr).await { + panic!("Expected ping to fail as mainnet/testnet history nodes shouldn't be able to communicate {pong:?}"); + }; +} + pub async fn test_find_nodes(protocol: ProtocolId, target: &Client, peertest: &Peertest) { info!("Testing find_nodes for {protocol}"); let bootnode_enr = peertest.bootnode.enr.clone(); diff --git a/ethportal-peertest/src/scenarios/gossip.rs b/ethportal-peertest/src/scenarios/gossip.rs index b47e71dd9..6d884b44f 100644 --- a/ethportal-peertest/src/scenarios/gossip.rs +++ b/ethportal-peertest/src/scenarios/gossip.rs @@ -42,7 +42,7 @@ pub async fn test_gossip_with_trace(peertest: &Peertest, target: &Client) { let trin_config = TrinConfig::new_from( [ "trin", - "--networks", + "--portal-subnetworks", "history,state", "--external-address", external_addr.as_str(), diff --git a/portal-bridge/src/client_handles.rs b/portal-bridge/src/client_handles.rs index 141e53444..b0643495e 100644 --- a/portal-bridge/src/client_handles.rs +++ b/portal-bridge/src/client_handles.rs @@ -60,7 +60,7 @@ pub fn trin_handle( .args(["--ephemeral"]) .args(["--mb", "0"]) .args(["--web3-transport", "http"]) - .args(["--networks", &networks]) + .args(["--portal-subnetworks", &networks]) .args(["--unsafe-private-key", &private_key]) .args([ "--web3-http-address", diff --git a/portalnet/src/discovery.rs b/portalnet/src/discovery.rs index c3f7b8129..a9e040cf0 100644 --- a/portalnet/src/discovery.rs +++ b/portalnet/src/discovery.rs @@ -1,5 +1,4 @@ use std::{ - convert::TryFrom, fmt, fs, hash::{Hash, Hasher}, io, @@ -25,8 +24,12 @@ use utp_rs::{cid::ConnectionPeer, udp::AsyncUdpSocket}; use super::config::PortalnetConfig; use crate::socket; use ethportal_api::{ - types::{discv5::RoutingTableInfo, enr::Enr, portal_wire::ProtocolId}, - utils::bytes::hex_encode, + types::{ + discv5::RoutingTableInfo, + enr::Enr, + portal_wire::{NetworkSpec, ProtocolId}, + }, + utils::bytes::{hex_decode, hex_encode}, NodeInfo, }; use trin_utils::version::get_trin_version; @@ -61,6 +64,8 @@ pub struct Discovery { pub started: bool, /// The socket address that the Discv5 service listens on. pub listen_socket: SocketAddr, + /// The Portal Network to Protocal Id Map etc MAINNET, TESTNET + network_spec: Arc, } impl fmt::Debug for Discovery { @@ -76,7 +81,11 @@ impl fmt::Debug for Discovery { } impl Discovery { - pub fn new(portal_config: PortalnetConfig, node_data_dir: PathBuf) -> Result { + pub fn new( + portal_config: PortalnetConfig, + node_data_dir: PathBuf, + network_spec: Arc, + ) -> Result { let listen_all_ips = SocketAddr::new( "0.0.0.0" .parse() @@ -194,6 +203,7 @@ impl Discovery { node_addr_cache, started: false, listen_socket: listen_all_ips, + network_spec, }) } @@ -323,7 +333,12 @@ impl Discovery { request: ProtocolRequest, ) -> Result, RequestError> { // Send empty protocol id if unable to convert it to bytes - let protocol = Vec::try_from(protocol).unwrap_or_default(); + let protocol = match self.network_spec.get_protocol_hex_from_id(&protocol) { + Ok(protocol_id) => hex_decode(&protocol_id).unwrap_or_default(), + Err(err) => { + unreachable!("send_talk_req() should never receive an invalid ProtocolId protocol: err={err}"); + } + }; let response = self.discv5.talk_req(enr, protocol, request).await?; Ok(response) @@ -442,7 +457,7 @@ impl AsyncUdpSocket for Discv5UdpSocket { mod tests { use super::*; use crate::utils::db::{configure_node_data_dir, configure_trin_data_dir}; - use ethportal_api::types::bootnodes::Bootnodes; + use ethportal_api::types::{bootnodes::Bootnodes, portal_wire::MAINNET}; #[test] fn test_enr_file() { @@ -450,7 +465,8 @@ mod tests { let trin_data_dir = configure_trin_data_dir(true).unwrap(); // Configure node data dir based on the provided private key - let (node_data_dir, private_key) = configure_node_data_dir(trin_data_dir, None).unwrap(); + let (node_data_dir, private_key) = + configure_node_data_dir(trin_data_dir, None, "test".to_string()).unwrap(); let mut portalnet_config = PortalnetConfig { private_key, @@ -463,7 +479,12 @@ mod tests { assert!(!trin_enr_file_location.is_file()); // test trin.enr is made on first run - let discovery = Discovery::new(portalnet_config.clone(), node_data_dir.clone()).unwrap(); + let discovery = Discovery::new( + portalnet_config.clone(), + node_data_dir.clone(), + MAINNET.clone(), + ) + .unwrap(); let data = fs::read_to_string(trin_enr_file_location.clone()).unwrap(); let old_enr = Enr::from_str(&data).unwrap(); assert_eq!(discovery.local_enr(), old_enr); @@ -471,7 +492,12 @@ mod tests { // test if Enr changes the Enr sequence is increased and if it is written to disk portalnet_config.listen_port = 2424; - let discovery = Discovery::new(portalnet_config.clone(), node_data_dir.clone()).unwrap(); + let discovery = Discovery::new( + portalnet_config.clone(), + node_data_dir.clone(), + MAINNET.clone(), + ) + .unwrap(); assert_ne!(discovery.local_enr(), old_enr); let data = fs::read_to_string(trin_enr_file_location.clone()).unwrap(); let old_enr = Enr::from_str(&data).unwrap(); @@ -480,7 +506,7 @@ mod tests { assert_eq!(discovery.local_enr(), old_enr); // test if the enr isn't changed that it's sequence stays the same - let discovery = Discovery::new(portalnet_config, node_data_dir).unwrap(); + let discovery = Discovery::new(portalnet_config, node_data_dir, MAINNET.clone()).unwrap(); assert_eq!(discovery.local_enr(), old_enr); let data = fs::read_to_string(trin_enr_file_location).unwrap(); let old_enr = Enr::from_str(&data).unwrap(); diff --git a/portalnet/src/events.rs b/portalnet/src/events.rs index 8fb728177..e2e303046 100644 --- a/portalnet/src/events.rs +++ b/portalnet/src/events.rs @@ -1,5 +1,5 @@ use std::{ - str::FromStr, + sync::Arc, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -10,7 +10,7 @@ use tokio_stream::wrappers::BroadcastStream; use tracing::{debug, error, trace, warn}; use ethportal_api::{ - types::portal_wire::ProtocolId, + types::portal_wire::{NetworkSpec, ProtocolId}, utils::bytes::{hex_encode, hex_encode_upper}, }; @@ -63,6 +63,8 @@ pub struct PortalnetEvents { pub beacon_handle: OverlayHandle, /// Send TalkReq events with "utp" protocol id to `UtpListener` pub utp_talk_reqs: mpsc::UnboundedSender, + /// The Portal Network to Protocal Id Map etc MAINNET, TESTNET + network_spec: Arc, } impl PortalnetEvents { @@ -72,6 +74,7 @@ impl PortalnetEvents { state_channels: OverlayChannels, beacon_channels: OverlayChannels, utp_talk_reqs: mpsc::UnboundedSender, + network_spec: Arc, ) -> Self { Self { talk_req_receiver, @@ -79,6 +82,7 @@ impl PortalnetEvents { state_handle: state_channels.into(), beacon_handle: beacon_channels.into(), utp_talk_reqs, + network_spec, } } @@ -118,7 +122,9 @@ impl PortalnetEvents { /// Dispatch Discv5 TalkRequest event to overlay networks or uTP socket fn dispatch_discv5_talk_req(&self, request: TalkRequest) { - let protocol_id = ProtocolId::from_str(&hex_encode_upper(request.protocol())); + let protocol_id = self + .network_spec + .get_protocol_id_from_hex(&hex_encode_upper(request.protocol())); match protocol_id { Ok(protocol) => match protocol { @@ -144,14 +150,19 @@ impl PortalnetEvents { } _ => { warn!( - "Received TalkRequest on unknown protocol from={} protocol={} body={}", + "Received TalkRequest on non-supported protocol from={} protocol={} body={}", request.node_id(), hex_encode_upper(request.protocol()), hex_encode(request.body()), ); } }, - Err(_) => warn!("Unable to decode protocol id"), + Err(err) => warn!( + "Received TalkRequest on unknown protocol from={} protocol={} body={} err={err}", + request.node_id(), + hex_encode_upper(request.protocol()), + hex_encode(request.body()), + ), } } diff --git a/portalnet/src/overlay/service.rs b/portalnet/src/overlay/service.rs index 520f18fc7..49c6fdad1 100644 --- a/portalnet/src/overlay/service.rs +++ b/portalnet/src/overlay/service.rs @@ -2671,6 +2671,7 @@ mod tests { content_key::overlay::IdentityContentKey, distance::XorMetric, enr::generate_random_remote_enr, + portal_wire::MAINNET, }; use trin_metrics::portalnet::PORTALNET_METRICS; use trin_storage::{DistanceFunction, MemoryContentStore}; @@ -2689,7 +2690,7 @@ mod tests { ..Default::default() }; let temp_dir = setup_temp_dir().unwrap().into_path(); - let discovery = Arc::new(Discovery::new(portal_config, temp_dir).unwrap()); + let discovery = Arc::new(Discovery::new(portal_config, temp_dir, MAINNET.clone()).unwrap()); let (_utp_talk_req_tx, utp_talk_req_rx) = unbounded_channel(); let discv5_utp = diff --git a/portalnet/src/utils/db.rs b/portalnet/src/utils/db.rs index ba9d7f71c..6be6f2bb8 100644 --- a/portalnet/src/utils/db.rs +++ b/portalnet/src/utils/db.rs @@ -10,7 +10,10 @@ use discv5::enr::{CombinedKey, Enr, NodeId}; use tempfile::TempDir; use tracing::debug; -use ethportal_api::utils::bytes::{hex_decode, hex_encode}; +use ethportal_api::{ + types::cli::DEFAULT_NETWORK, + utils::bytes::{hex_decode, hex_encode}, +}; const TRIN_DATA_ENV_VAR: &str = "TRIN_DATA_PATH"; const TRIN_DATA_DIR: &str = "trin"; @@ -49,6 +52,7 @@ pub fn configure_trin_data_dir(ephemeral: bool) -> anyhow::Result { pub fn configure_node_data_dir( trin_data_dir: PathBuf, private_key: Option, + network_name: String, ) -> anyhow::Result<(PathBuf, B256)> { let pk = match private_key { // user has provided a custom private key... @@ -57,15 +61,20 @@ pub fn configure_node_data_dir( None => get_application_private_key(&trin_data_dir)?, }; let node_id = Enr::empty(&pk)?.node_id(); - let node_data_dir = get_node_data_dir(trin_data_dir, node_id); + let node_data_dir = get_node_data_dir(trin_data_dir, node_id, network_name); fs::create_dir_all(&node_data_dir)?; Ok((node_data_dir, B256::from_slice(&pk.encode()))) } /// Returns the node data directory associated with the provided node id. -fn get_node_data_dir(trin_data_dir: PathBuf, node_id: NodeId) -> PathBuf { +fn get_node_data_dir(trin_data_dir: PathBuf, node_id: NodeId, network_name: String) -> PathBuf { // Append first 8 characters of Node ID - let mut application_string = "trin_".to_owned(); + let mut application_string = "".to_owned(); + if network_name != DEFAULT_NETWORK { + application_string.push_str(&network_name); + application_string.push('_'); + } + application_string.push_str("trin_"); let node_id_string = hex::encode(node_id.raw()); let suffix = &node_id_string[..8]; application_string.push_str(suffix); @@ -110,7 +119,9 @@ pub mod test { #[serial] fn app_private_key() { let temp_dir = setup_temp_dir().unwrap(); - let (_, active_pk) = configure_node_data_dir(temp_dir.path().to_path_buf(), None).unwrap(); + let (_, active_pk) = + configure_node_data_dir(temp_dir.path().to_path_buf(), None, "test".to_string()) + .unwrap(); let app_pk = get_application_private_key(temp_dir.path()).unwrap(); let app_pk = B256::from_slice(&app_pk.encode()); temp_dir.close().unwrap(); @@ -124,7 +135,8 @@ pub mod test { let pk = CombinedKey::generate_secp256k1(); let pk = B256::from_slice(&pk.encode()); let (_, active_pk) = - configure_node_data_dir(temp_dir.path().to_path_buf(), Some(pk)).unwrap(); + configure_node_data_dir(temp_dir.path().to_path_buf(), Some(pk), "test".to_string()) + .unwrap(); temp_dir.close().unwrap(); assert_eq!(pk, active_pk); } @@ -133,15 +145,21 @@ pub mod test { #[serial] fn activated_private_key_persists_over_reconfigurations() { let temp_dir = setup_temp_dir().unwrap(); - let (_, app_pk) = configure_node_data_dir(temp_dir.path().to_path_buf(), None).unwrap(); + let (_, app_pk) = + configure_node_data_dir(temp_dir.path().to_path_buf(), None, "test".to_string()) + .unwrap(); // configure data dir to use a custom pk let pk = CombinedKey::generate_secp256k1(); let pk = B256::from_slice(&pk.encode()); - let _ = configure_node_data_dir(temp_dir.path().to_path_buf(), Some(pk)).unwrap(); + let _ = + configure_node_data_dir(temp_dir.path().to_path_buf(), Some(pk), "test".to_string()) + .unwrap(); // reconfigure data dir with no pk, should use the original app pk - let (_, app_pk_2) = configure_node_data_dir(temp_dir.path().to_path_buf(), None).unwrap(); + let (_, app_pk_2) = + configure_node_data_dir(temp_dir.path().to_path_buf(), None, "test".to_string()) + .unwrap(); temp_dir.close().unwrap(); assert_eq!(app_pk, app_pk_2); } diff --git a/portalnet/tests/overlay.rs b/portalnet/tests/overlay.rs index ce64c60ef..15d27921f 100644 --- a/portalnet/tests/overlay.rs +++ b/portalnet/tests/overlay.rs @@ -1,6 +1,5 @@ use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, - str::FromStr, sync::Arc, }; @@ -17,7 +16,7 @@ use ethportal_api::{ content_key::overlay::IdentityContentKey, distance::XorMetric, enr::{Enr, SszEnr}, - portal_wire::{Content, Message, ProtocolId}, + portal_wire::{Content, Message, ProtocolId, MAINNET}, }, utils::bytes::hex_encode_upper, }; @@ -66,7 +65,8 @@ async fn spawn_overlay( let overlay_protocol = *overlay.protocol(); tokio::spawn(async move { while let Some(talk_req) = talk_req_rx.recv().await { - let req_protocol = ProtocolId::from_str(&hex_encode_upper(talk_req.protocol())); + let req_protocol = + MAINNET.get_protocol_id_from_hex(&hex_encode_upper(talk_req.protocol())); if let Ok(req_protocol) = req_protocol { match (req_protocol, overlay_protocol) { @@ -110,7 +110,8 @@ async fn overlay() { ..PortalnetConfig::default() }; let temp_dir_one = setup_temp_dir().unwrap().into_path(); - let mut discovery_one = Discovery::new(portal_config_one, temp_dir_one).unwrap(); + let mut discovery_one = + Discovery::new(portal_config_one, temp_dir_one, MAINNET.clone()).unwrap(); let talk_req_rx_one = discovery_one.start().await.unwrap(); let discovery_one = Arc::new(discovery_one); let overlay_one = Arc::new(init_overlay(Arc::clone(&discovery_one), protocol).await); @@ -124,7 +125,8 @@ async fn overlay() { ..PortalnetConfig::default() }; let temp_dir_two = setup_temp_dir().unwrap().into_path(); - let mut discovery_two = Discovery::new(portal_config_two, temp_dir_two).unwrap(); + let mut discovery_two = + Discovery::new(portal_config_two, temp_dir_two, MAINNET.clone()).unwrap(); let talk_req_rx_two = discovery_two.start().await.unwrap(); let discovery_two = Arc::new(discovery_two); let overlay_two = Arc::new(init_overlay(Arc::clone(&discovery_two), protocol).await); @@ -138,7 +140,8 @@ async fn overlay() { ..PortalnetConfig::default() }; let temp_dir_three = setup_temp_dir().unwrap().into_path(); - let mut discovery_three = Discovery::new(portal_config_three, temp_dir_three).unwrap(); + let mut discovery_three = + Discovery::new(portal_config_three, temp_dir_three, MAINNET.clone()).unwrap(); let talk_req_rx_three = discovery_three.start().await.unwrap(); let discovery_three = Arc::new(discovery_three); let overlay_three = Arc::new(init_overlay(Arc::clone(&discovery_three), protocol).await); @@ -255,7 +258,7 @@ async fn overlay_event_stream() { ..Default::default() }; let temp_dir = setup_temp_dir().unwrap().into_path(); - let discovery = Arc::new(Discovery::new(portal_config, temp_dir).unwrap()); + let discovery = Arc::new(Discovery::new(portal_config, temp_dir, MAINNET.clone()).unwrap()); let overlay = init_overlay(discovery, ProtocolId::Beacon).await; overlay.event_stream().await.unwrap(); diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 2b275b7fe..0ab80fe21 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -51,7 +51,7 @@ pub async fn launch_jsonrpc_server( // Discv5 and Web3 modules are enabled with every network let mut modules = vec![PortalRpcModule::Discv5, PortalRpcModule::Web3]; - for network in trin_config.networks.iter() { + for network in trin_config.portal_subnetworks.iter() { match network.as_str() { HISTORY_NETWORK => { modules.push(PortalRpcModule::History); diff --git a/rpc/src/rpc_server.rs b/rpc/src/rpc_server.rs index bc4b5ba88..97e8daa0e 100644 --- a/rpc/src/rpc_server.rs +++ b/rpc/src/rpc_server.rs @@ -615,6 +615,7 @@ impl WsHttpServerKind { mod tests { use super::*; use crate::{builder::RpcModuleSelection, PortalRpcModule, RpcModuleBuilder}; + use ethportal_api::types::portal_wire::MAINNET; use portalnet::{discovery::Discovery, utils::db::setup_temp_dir}; use std::{io, sync::Arc}; @@ -637,7 +638,8 @@ mod tests { let (history_tx, _) = tokio::sync::mpsc::unbounded_channel(); let (beacon_tx, _) = tokio::sync::mpsc::unbounded_channel(); let temp_dir = setup_temp_dir().unwrap().into_path(); - let discv5 = Arc::new(Discovery::new(Default::default(), temp_dir).unwrap()); + let discv5 = + Arc::new(Discovery::new(Default::default(), temp_dir, MAINNET.clone()).unwrap()); RpcModuleBuilder::new(discv5) .with_history(history_tx) .with_beacon(beacon_tx) diff --git a/src/lib.rs b/src/lib.rs index 8e0ece592..3b02626c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,13 +42,20 @@ pub async fn run_trin( let trin_data_dir = configure_trin_data_dir(trin_config.ephemeral)?; // Configure node data dir based on the provided private key - let (node_data_dir, private_key) = - configure_node_data_dir(trin_data_dir, trin_config.private_key)?; + let (node_data_dir, private_key) = configure_node_data_dir( + trin_data_dir, + trin_config.private_key, + trin_config.network.get_network_name().to_string(), + )?; let portalnet_config = PortalnetConfig::new(&trin_config, private_key); // Initialize base discovery protocol - let mut discovery = Discovery::new(portalnet_config.clone(), node_data_dir.clone())?; + let mut discovery = Discovery::new( + portalnet_config.clone(), + node_data_dir.clone(), + trin_config.network.clone(), + )?; let talk_req_rx = discovery.start().await?; let discovery = Arc::new(discovery); @@ -80,7 +87,10 @@ pub async fn run_trin( // Initialize state sub-network service and event handlers, if selected let (state_handler, state_network_task, state_event_tx, state_jsonrpc_tx, state_event_stream) = - if trin_config.networks.iter().any(|val| val == STATE_NETWORK) { + if trin_config + .portal_subnetworks + .contains(&STATE_NETWORK.to_string()) + { initialize_state_network( &discovery, utp_socket.clone(), @@ -100,7 +110,10 @@ pub async fn run_trin( beacon_event_tx, beacon_jsonrpc_tx, beacon_event_stream, - ) = if trin_config.networks.iter().any(|val| val == BEACON_NETWORK) { + ) = if trin_config + .portal_subnetworks + .contains(&BEACON_NETWORK.to_string()) + { initialize_beacon_network( &discovery, utp_socket.clone(), @@ -121,9 +134,8 @@ pub async fn run_trin( history_jsonrpc_tx, history_event_stream, ) = if trin_config - .networks - .iter() - .any(|val| val == HISTORY_NETWORK) + .portal_subnetworks + .contains(&HISTORY_NETWORK.to_string()) { initialize_history_network( &discovery, @@ -167,6 +179,7 @@ pub async fn run_trin( (state_event_tx, state_event_stream), (beacon_event_tx, beacon_event_stream), utp_talk_reqs_tx, + trin_config.network.clone(), ) .await; events.start().await; diff --git a/tests/self_peertest.rs b/tests/self_peertest.rs index 95e7477fd..07115bba7 100644 --- a/tests/self_peertest.rs +++ b/tests/self_peertest.rs @@ -26,7 +26,7 @@ async fn peertest_stateless() { // without needing to reset the database between tests. // If a scenario is testing the state of the content database, // it should be added to its own test function. - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::paginate::test_paginate_local_storage(&peertest).await; peertest::scenarios::basic::test_web3_client_version(&target).await; @@ -59,7 +59,7 @@ async fn peertest_stateless() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_populated_offer() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::offer_accept::test_populated_offer(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -68,7 +68,7 @@ async fn peertest_populated_offer() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_unpopulated_offer() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::offer_accept::test_unpopulated_offer(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -77,7 +77,7 @@ async fn peertest_unpopulated_offer() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_gossip_with_trace() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::gossip::test_gossip_with_trace(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -86,7 +86,7 @@ async fn peertest_gossip_with_trace() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_find_content_return_enr() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::find::test_find_content_return_enr(&target, &peertest).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -95,7 +95,7 @@ async fn peertest_find_content_return_enr() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_trace_recursive_find_content_local_db() { - let (peertest, _target, handle) = setup_peertest().await; + let (peertest, _target, handle) = setup_peertest("mainnet").await; peertest::scenarios::find::test_trace_recursive_find_content_local_db(&peertest).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -104,7 +104,7 @@ async fn peertest_trace_recursive_find_content_local_db() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_trace_recursive_find_content_for_absent_content() { - let (peertest, _target, handle) = setup_peertest().await; + let (peertest, _target, handle) = setup_peertest("mainnet").await; peertest::scenarios::find::test_trace_recursive_find_content_for_absent_content(&peertest) .await; peertest.exit_all_nodes(); @@ -114,7 +114,7 @@ async fn peertest_trace_recursive_find_content_for_absent_content() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_trace_recursive_find_content() { - let (peertest, _target, handle) = setup_peertest().await; + let (peertest, _target, handle) = setup_peertest("mainnet").await; peertest::scenarios::find::test_trace_recursive_find_content(&peertest).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -123,7 +123,7 @@ async fn peertest_trace_recursive_find_content() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_validate_pre_merge_header_with_proof() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::validation::test_validate_pre_merge_header_with_proof(&peertest, &target) .await; peertest.exit_all_nodes(); @@ -133,7 +133,7 @@ async fn peertest_validate_pre_merge_header_with_proof() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_invalidate_header_by_hash() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::validation::test_invalidate_header_by_hash(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -142,7 +142,7 @@ async fn peertest_invalidate_header_by_hash() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_validate_block_body() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::validation::test_validate_pre_merge_block_body(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -151,7 +151,7 @@ async fn peertest_validate_block_body() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_validate_receipts() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::validation::test_validate_pre_merge_receipts(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -160,7 +160,7 @@ async fn peertest_validate_receipts() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_recursive_utp() { - let (peertest, _target, handle) = setup_peertest().await; + let (peertest, _target, handle) = setup_peertest("mainnet").await; peertest::scenarios::utp::test_recursive_utp(&peertest).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -169,7 +169,7 @@ async fn peertest_recursive_utp() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_trace_recursive_utp() { - let (peertest, _target, handle) = setup_peertest().await; + let (peertest, _target, handle) = setup_peertest("mainnet").await; peertest::scenarios::utp::test_trace_recursive_utp(&peertest).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -178,7 +178,7 @@ async fn peertest_trace_recursive_utp() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_state_offer_account_trie_node() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::state::test_state_offer_account_trie_node(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -187,7 +187,7 @@ async fn peertest_state_offer_account_trie_node() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_state_offer_contract_storage_trie_node() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::state::test_state_gossip_contract_storage_trie_node(&peertest, &target) .await; peertest.exit_all_nodes(); @@ -197,7 +197,7 @@ async fn peertest_state_offer_contract_storage_trie_node() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_state_offer_contract_bytecode() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::state::test_state_gossip_contract_bytecode(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); @@ -206,13 +206,22 @@ async fn peertest_state_offer_contract_bytecode() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn peertest_state_recursive_gossip() { - let (peertest, target, handle) = setup_peertest().await; + let (peertest, target, handle) = setup_peertest("mainnet").await; peertest::scenarios::state::test_state_recursive_gossip(&peertest, &target).await; peertest.exit_all_nodes(); handle.stop().unwrap(); } -async fn setup_peertest() -> (peertest::Peertest, Client, RpcServerHandle) { +#[tokio::test(flavor = "multi_thread")] +#[serial] +async fn peertest_ping_cross_discv5_protocol_id() { + let (peertest, target, handle) = setup_peertest("testnet").await; + peertest::scenarios::basic::test_ping_cross_network(&target, &peertest).await; + peertest.exit_all_nodes(); + handle.stop().unwrap(); +} + +async fn setup_peertest(network: &str) -> (peertest::Peertest, Client, RpcServerHandle) { utils::init_tracing(); // Run a client, as a buddy peer for ping tests, etc. let peertest = peertest::launch_peertest_nodes(2).await; @@ -228,7 +237,7 @@ async fn setup_peertest() -> (peertest::Peertest, Client, RpcServerHandle) { let trin_config = TrinConfig::new_from( [ "trin", - "--networks", + "--portal-subnetworks", "history,beacon,state", "--external-address", external_addr.as_str(), @@ -239,6 +248,8 @@ async fn setup_peertest() -> (peertest::Peertest, Client, RpcServerHandle) { test_discovery_port.to_string().as_ref(), "--bootnodes", "none", + "--network", + network, ] .iter(), ) @@ -271,7 +282,7 @@ async fn setup_peertest_bridge() -> (Peertest, HttpClient, RpcServerHandle) { let trin_config = TrinConfig::new_from( [ "trin", - "--networks", + "--portal-subnetworks", "history,beacon,state", "--external-address", external_addr.as_str(), diff --git a/trin-history/src/storage.rs b/trin-history/src/storage.rs index 61672bfa4..6707b8bcf 100644 --- a/trin-history/src/storage.rs +++ b/trin-history/src/storage.rs @@ -94,7 +94,7 @@ pub mod test { const CAPACITY_MB: u64 = 2; fn get_active_node_id(temp_dir: PathBuf) -> NodeId { - let (_, mut pk) = configure_node_data_dir(temp_dir, None).unwrap(); + let (_, mut pk) = configure_node_data_dir(temp_dir, None, "test".to_string()).unwrap(); let pk = CombinedKey::secp256k1_from_bytes(pk.0.as_mut_slice()).unwrap(); Discv5Enr::empty(&pk).unwrap().node_id() } diff --git a/utp-testing/src/lib.rs b/utp-testing/src/lib.rs index 06c574464..e68dfdfe9 100644 --- a/utp-testing/src/lib.rs +++ b/utp-testing/src/lib.rs @@ -8,7 +8,10 @@ pub mod rpc; use crate::rpc::RpcServer; use discv5::TalkRequest; use ethportal_api::{ - types::{enr::Enr, portal_wire::ProtocolId}, + types::{ + enr::Enr, + portal_wire::{ProtocolId, MAINNET}, + }, utils::bytes::{hex_encode, hex_encode_upper}, }; use jsonrpsee::{ @@ -141,8 +144,9 @@ impl TestApp { // Forward discv5 uTP packets to uTP socket tokio::spawn(async move { while let Some(request) = talk_req_rx.recv().await { - let protocol_id = - ProtocolId::from_str(&hex_encode_upper(request.protocol())).unwrap(); + let protocol_id = MAINNET + .get_protocol_id_from_hex(&hex_encode_upper(request.protocol())) + .unwrap(); if let ProtocolId::Utp = protocol_id { utp_talk_reqs_tx.send(request).unwrap(); @@ -166,7 +170,7 @@ pub async fn run_test_app( }; let temp_dir = setup_temp_dir().unwrap().into_path(); - let mut discovery = Discovery::new(config, temp_dir).unwrap(); + let mut discovery = Discovery::new(config, temp_dir, MAINNET.clone()).unwrap(); let talk_req_rx = discovery.start().await.unwrap(); let enr = discovery.local_enr(); let discovery = Arc::new(discovery);