diff --git a/Cargo.lock b/Cargo.lock index e6d3183c8d..e026f82310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -763,6 +763,7 @@ dependencies = [ "ant-bootstrap", "ant-build-info", "ant-logging", + "ant-protocol", "autonomi", "clap", "color-eyre", diff --git a/ant-bootstrap/src/config.rs b/ant-bootstrap/src/config.rs index 131d857694..b2c88561be 100644 --- a/ant-bootstrap/src/config.rs +++ b/ant-bootstrap/src/config.rs @@ -7,7 +7,7 @@ // permissions and limitations relating to use of the SAFE Network Software. use crate::error::{Error, Result}; -use ant_protocol::version::{get_key_version_str, get_truncate_version_str}; +use ant_protocol::version::{get_network_id, get_truncate_version_str}; use std::{ path::{Path, PathBuf}, time::Duration, @@ -125,6 +125,6 @@ fn default_cache_path() -> Result { /// Returns the name of the cache file pub fn cache_file_name() -> String { - let network_id = format!("{}_{}", get_key_version_str(), get_truncate_version_str()); + let network_id = format!("{}_{}", get_network_id(), get_truncate_version_str()); format!("bootstrap_cache_{network_id}.json") } diff --git a/ant-cli/Cargo.toml b/ant-cli/Cargo.toml index 40fa0f182b..77c9343190 100644 --- a/ant-cli/Cargo.toml +++ b/ant-cli/Cargo.toml @@ -27,6 +27,7 @@ harness = false ant-bootstrap = { path = "../ant-bootstrap", version = "0.1.0" } ant-build-info = { path = "../ant-build-info", version = "0.1.19" } ant-logging = { path = "../ant-logging", version = "0.2.40" } +ant-protocol = { path = "../ant-protocol", version = "0.17.15" } autonomi = { path = "../autonomi", version = "0.2.4", features = [ "fs", "vault", diff --git a/ant-cli/src/main.rs b/ant-cli/src/main.rs index b50092e538..c0404e9f75 100644 --- a/ant-cli/src/main.rs +++ b/ant-cli/src/main.rs @@ -34,6 +34,9 @@ use tracing::Level; async fn main() -> Result<()> { color_eyre::install().expect("Failed to initialise error handler"); let opt = Opt::parse(); + if let Some(network_id) = opt.network_id { + ant_protocol::version::set_network_id(network_id); + } let _log_guards = init_logging_and_metrics(&opt)?; #[cfg(feature = "metrics")] tokio::spawn(init_metrics(std::process::id())); diff --git a/ant-cli/src/opt.rs b/ant-cli/src/opt.rs index 3e84379fc0..3ffa1eb5f6 100644 --- a/ant-cli/src/opt.rs +++ b/ant-cli/src/opt.rs @@ -51,6 +51,12 @@ pub(crate) struct Opt { #[clap(long = "timeout", global = true, value_parser = |t: &str| -> Result { Ok(t.parse().map(Duration::from_secs)?) })] pub connection_timeout: Option, + /// Specify the network ID to use. This will allow you to run the CLI on a different network. + /// + /// By default, the network ID is set to 1, which represents the mainnet. + #[clap(long, verbatim_doc_comment)] + pub network_id: Option, + /// Prevent verification of data storage on the network. /// /// This may increase operation speed, but offers no guarantees that operations were successful. diff --git a/ant-networking/src/driver.rs b/ant-networking/src/driver.rs index 59a6c353ff..eb34b13e2a 100644 --- a/ant-networking/src/driver.rs +++ b/ant-networking/src/driver.rs @@ -35,7 +35,7 @@ use ant_protocol::{ messages::{ChunkProof, Nonce, Request, Response}, storage::{try_deserialize_record, RetryStrategy}, version::{ - get_key_version_str, IDENTIFY_CLIENT_VERSION_STR, IDENTIFY_NODE_VERSION_STR, + get_network_id, IDENTIFY_CLIENT_VERSION_STR, IDENTIFY_NODE_VERSION_STR, IDENTIFY_PROTOCOL_STR, REQ_RESPONSE_VERSION_STR, }, NetworkAddress, PrettyPrintKBucketKey, PrettyPrintRecordKey, @@ -267,16 +267,16 @@ pub(super) struct NodeBehaviour { #[derive(Debug)] pub struct NetworkBuilder { bootstrap_cache: Option, + concurrency_limit: Option, is_behind_home_network: bool, keypair: Keypair, - local: bool, listen_addr: Option, - request_timeout: Option, - concurrency_limit: Option, + local: bool, #[cfg(feature = "open-metrics")] metrics_registries: Option, #[cfg(feature = "open-metrics")] metrics_server_port: Option, + request_timeout: Option, #[cfg(feature = "upnp")] upnp: bool, } @@ -285,16 +285,16 @@ impl NetworkBuilder { pub fn new(keypair: Keypair, local: bool) -> Self { Self { bootstrap_cache: None, + concurrency_limit: None, is_behind_home_network: false, keypair, - local, listen_addr: None, - request_timeout: None, - concurrency_limit: None, + local, #[cfg(feature = "open-metrics")] metrics_registries: None, #[cfg(feature = "open-metrics")] metrics_server_port: None, + request_timeout: None, #[cfg(feature = "upnp")] upnp: false, } @@ -394,7 +394,7 @@ impl NetworkBuilder { check_and_wipe_storage_dir_if_necessary( root_dir.clone(), storage_dir_path.clone(), - get_key_version_str(), + get_network_id(), )?; // Configures the disk_store to store records under the provided path and increase the max record size @@ -431,7 +431,6 @@ impl NetworkBuilder { Some(store_cfg), false, ProtocolSupport::Full, - IDENTIFY_NODE_VERSION_STR.to_string(), #[cfg(feature = "upnp")] upnp, )?; @@ -482,7 +481,6 @@ impl NetworkBuilder { None, true, ProtocolSupport::Outbound, - IDENTIFY_CLIENT_VERSION_STR.to_string(), #[cfg(feature = "upnp")] false, )?; @@ -497,9 +495,13 @@ impl NetworkBuilder { record_store_cfg: Option, is_client: bool, req_res_protocol: ProtocolSupport, - identify_version: String, #[cfg(feature = "upnp")] upnp: bool, ) -> Result<(Network, mpsc::Receiver, SwarmDriver)> { + let identify_protocol_str = IDENTIFY_PROTOCOL_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_PROTOCOL_STR") + .clone(); + let peer_id = PeerId::from(self.keypair.public()); // vdash metric (if modified please notify at https://github.com/happybeing/vdash/issues): #[cfg(not(target_arch = "wasm32"))] @@ -563,7 +565,7 @@ impl NetworkBuilder { "The protocol version string that is used to connect to the correct network", Info::new(vec![( "identify_protocol_str".to_string(), - IDENTIFY_PROTOCOL_STR.to_string(), + identify_protocol_str.clone(), )]), ); @@ -577,14 +579,16 @@ impl NetworkBuilder { let request_response = { let cfg = RequestResponseConfig::default() .with_request_timeout(self.request_timeout.unwrap_or(REQUEST_TIMEOUT_DEFAULT_S)); + let req_res_version_str = REQ_RESPONSE_VERSION_STR + .read() + .expect("Failed to obtain read lock for REQ_RESPONSE_VERSION_STR") + .clone(); - info!( - "Building request response with {:?}", - REQ_RESPONSE_VERSION_STR.as_str() - ); + info!("Building request response with {req_res_version_str:?}",); request_response::cbor::Behaviour::new( [( - StreamProtocol::new(&REQ_RESPONSE_VERSION_STR), + StreamProtocol::try_from_owned(req_res_version_str) + .expect("StreamProtocol should start with a /"), req_res_protocol, )], cfg, @@ -640,12 +644,22 @@ impl NetworkBuilder { #[cfg(feature = "local")] let mdns = mdns::tokio::Behaviour::new(mdns_config, peer_id)?; + let agent_version = if is_client { + IDENTIFY_CLIENT_VERSION_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_CLIENT_VERSION_STR") + .clone() + } else { + IDENTIFY_NODE_VERSION_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_NODE_VERSION_STR") + .clone() + }; // Identify Behaviour - let identify_protocol_str = IDENTIFY_PROTOCOL_STR.to_string(); - info!("Building Identify with identify_protocol_str: {identify_protocol_str:?} and identify_version: {identify_version:?}"); + info!("Building Identify with identify_protocol_str: {identify_protocol_str:?} and identify_protocol_str: {identify_protocol_str:?}"); let identify = { let cfg = libp2p::identify::Config::new(identify_protocol_str, self.keypair.public()) - .with_agent_version(identify_version) + .with_agent_version(agent_version) // Enlength the identify interval from default 5 mins to 1 hour. .with_interval(RESEND_IDENTIFY_INVERVAL); libp2p::identify::Behaviour::new(cfg) diff --git a/ant-networking/src/event/swarm.rs b/ant-networking/src/event/swarm.rs index 84127c43d3..3bf65eb6d9 100644 --- a/ant-networking/src/event/swarm.rs +++ b/ant-networking/src/event/swarm.rs @@ -124,11 +124,13 @@ impl SwarmDriver { } => { debug!(conn_id=%connection_id, %peer_id, ?info, "identify: received info"); - if info.protocol_version != IDENTIFY_PROTOCOL_STR.to_string() { - warn!(?info.protocol_version, "identify: {peer_id:?} does not have the same protocol. Our IDENTIFY_PROTOCOL_STR: {:?}", IDENTIFY_PROTOCOL_STR.as_str()); + let our_identify_protocol = IDENTIFY_PROTOCOL_STR.read().expect("IDENTIFY_PROTOCOL_STR has been locked to write. A call to set_network_id performed. This should not happen.").to_string(); + + if info.protocol_version != our_identify_protocol { + warn!(?info.protocol_version, "identify: {peer_id:?} does not have the same protocol. Our IDENTIFY_PROTOCOL_STR: {our_identify_protocol:?}"); self.send_event(NetworkEvent::PeerWithUnsupportedProtocol { - our_protocol: IDENTIFY_PROTOCOL_STR.to_string(), + our_protocol: our_identify_protocol, their_protocol: info.protocol_version, }); // Block the peer from any further communication. @@ -143,8 +145,9 @@ impl SwarmDriver { return Ok(()); } + let our_agent_version = IDENTIFY_NODE_VERSION_STR.read().expect("IDENTIFY_NODE_VERSION_STR has been locked to write. A call to set_network_id performed. This should not happen.").to_string(); // if client, return. - if info.agent_version != IDENTIFY_NODE_VERSION_STR.to_string() { + if info.agent_version != our_agent_version { return Ok(()); } diff --git a/ant-node-manager/src/add_services/config.rs b/ant-node-manager/src/add_services/config.rs index 40eea8ff86..7aac0eaeb6 100644 --- a/ant-node-manager/src/add_services/config.rs +++ b/ant-node-manager/src/add_services/config.rs @@ -79,6 +79,7 @@ pub struct InstallNodeServiceCtxBuilder { pub log_dir_path: PathBuf, pub log_format: Option, pub name: String, + pub network_id: Option, pub max_archived_log_files: Option, pub max_log_files: Option, pub metrics_port: Option, @@ -105,6 +106,10 @@ impl InstallNodeServiceCtxBuilder { ]; push_arguments_from_peers_args(&self.peers_args, &mut args); + if let Some(id) = self.network_id { + args.push(OsString::from("--network-id")); + args.push(OsString::from(id.to_string())); + } if self.home_network { args.push(OsString::from("--home-network")); } @@ -185,6 +190,7 @@ pub struct AddNodeServiceOptions { pub max_archived_log_files: Option, pub max_log_files: Option, pub metrics_port: Option, + pub network_id: Option, pub node_ip: Option, pub node_port: Option, pub owner: Option, @@ -314,10 +320,11 @@ mod tests { home_network: false, log_dir_path: PathBuf::from("/logs"), log_format: None, - name: "test-node".to_string(), max_archived_log_files: None, max_log_files: None, metrics_port: None, + name: "test-node".to_string(), + network_id: None, node_ip: None, node_port: None, owner: None, @@ -349,10 +356,11 @@ mod tests { home_network: false, log_dir_path: PathBuf::from("/logs"), log_format: None, - name: "test-node".to_string(), max_archived_log_files: None, max_log_files: None, metrics_port: None, + name: "test-node".to_string(), + network_id: None, node_ip: None, node_port: None, owner: None, @@ -385,10 +393,11 @@ mod tests { home_network: false, log_dir_path: PathBuf::from("/logs"), log_format: None, - name: "test-node".to_string(), max_archived_log_files: Some(10), max_log_files: Some(10), metrics_port: None, + name: "test-node".to_string(), + network_id: Some(5), node_ip: None, node_port: None, owner: None, @@ -510,6 +519,8 @@ mod tests { "http://localhost:8080", "--testnet", "--ignore-cache", + "--network-id", + "5", "--home-network", "--log-format", "json", diff --git a/ant-node-manager/src/add_services/mod.rs b/ant-node-manager/src/add_services/mod.rs index a871f73179..76e8d46c12 100644 --- a/ant-node-manager/src/add_services/mod.rs +++ b/ant-node-manager/src/add_services/mod.rs @@ -210,6 +210,7 @@ pub async fn add_node( max_log_files: options.max_log_files, metrics_port: metrics_free_port, name: service_name.clone(), + network_id: options.network_id, node_ip: options.node_ip, node_port, owner: owner.clone(), @@ -246,6 +247,7 @@ pub async fn add_node( max_archived_log_files: options.max_archived_log_files, max_log_files: options.max_log_files, metrics_port: metrics_free_port, + network_id: options.network_id, node_ip: options.node_ip, node_port, number: node_number, diff --git a/ant-node-manager/src/add_services/tests.rs b/ant-node-manager/src/add_services/tests.rs index ee19f167b0..58eaf31162 100644 --- a/ant-node-manager/src/add_services/tests.rs +++ b/ant-node-manager/src/add_services/tests.rs @@ -139,6 +139,7 @@ async fn add_genesis_node_should_use_latest_version_and_add_one_service() -> Res max_log_files: None, metrics_port: None, name: "antnode1".to_string(), + network_id: None, node_ip: None, node_port: None, owner: None, @@ -173,6 +174,7 @@ async fn add_genesis_node_should_use_latest_version_and_add_one_service() -> Res max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -294,6 +296,7 @@ async fn add_genesis_node_should_return_an_error_if_there_is_already_a_genesis_n max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -341,6 +344,7 @@ async fn add_genesis_node_should_return_an_error_if_there_is_already_a_genesis_n max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -430,6 +434,7 @@ async fn add_genesis_node_should_return_an_error_if_count_is_greater_than_1() -> max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -525,6 +530,7 @@ async fn add_node_should_use_latest_version_and_add_three_services() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -573,6 +579,7 @@ async fn add_node_should_use_latest_version_and_add_three_services() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode2".to_string(), node_ip: None, node_port: None, @@ -621,6 +628,7 @@ async fn add_node_should_use_latest_version_and_add_three_services() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode3".to_string(), node_ip: None, node_port: None, @@ -657,6 +665,7 @@ async fn add_node_should_use_latest_version_and_add_three_services() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -802,6 +811,7 @@ async fn add_node_should_update_the_environment_variables_inside_node_registry() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -837,6 +847,7 @@ async fn add_node_should_update_the_environment_variables_inside_node_registry() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -931,6 +942,7 @@ async fn add_new_node_should_add_another_service() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -987,6 +999,7 @@ async fn add_new_node_should_add_another_service() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode2".to_string(), node_ip: None, node_port: None, @@ -1023,6 +1036,7 @@ async fn add_new_node_should_add_another_service() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -1186,6 +1200,7 @@ async fn add_node_should_create_service_file_with_first_arg() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -1342,6 +1357,7 @@ async fn add_node_should_create_service_file_with_peers_args() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -1493,6 +1509,7 @@ async fn add_node_should_create_service_file_with_local_arg() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -1648,6 +1665,7 @@ async fn add_node_should_create_service_file_with_network_contacts_url_arg() -> max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -1802,6 +1820,7 @@ async fn add_node_should_create_service_file_with_testnet_arg() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -1953,6 +1972,7 @@ async fn add_node_should_create_service_file_with_ignore_cache_arg() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -2105,6 +2125,7 @@ async fn add_node_should_create_service_file_with_custom_bootstrap_cache_path() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -2152,6 +2173,148 @@ async fn add_node_should_create_service_file_with_custom_bootstrap_cache_path() Ok(()) } +#[tokio::test] +async fn add_node_should_create_service_file_with_network_id() -> Result<()> { + let tmp_data_dir = assert_fs::TempDir::new()?; + let node_reg_path = tmp_data_dir.child("node_reg.json"); + + let mut mock_service_control = MockServiceControl::new(); + + let mut node_registry = NodeRegistry { + auditor: None, + faucet: None, + save_path: node_reg_path.to_path_buf(), + nat_status: None, + nodes: vec![], + environment_variables: None, + daemon: None, + }; + let latest_version = "0.96.4"; + let temp_dir = assert_fs::TempDir::new()?; + let node_data_dir = temp_dir.child("data"); + node_data_dir.create_dir_all()?; + let node_logs_dir = temp_dir.child("logs"); + node_logs_dir.create_dir_all()?; + let antnode_download_path = temp_dir.child(ANTNODE_FILE_NAME); + antnode_download_path.write_binary(b"fake antnode bin")?; + + let mut seq = Sequence::new(); + + mock_service_control + .expect_get_available_port() + .times(1) + .returning(|| Ok(12001)) + .in_sequence(&mut seq); + + mock_service_control + .expect_install() + .times(1) + .with( + eq(ServiceInstallCtx { + args: vec![ + OsString::from("--rpc"), + OsString::from("127.0.0.1:12001"), + OsString::from("--root-dir"), + OsString::from( + node_data_dir + .to_path_buf() + .join("antnode1") + .to_string_lossy() + .to_string(), + ), + OsString::from("--log-output-dest"), + OsString::from( + node_logs_dir + .to_path_buf() + .join("antnode1") + .to_string_lossy() + .to_string(), + ), + OsString::from("--network-id"), + OsString::from("5"), + OsString::from("--rewards-address"), + OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"), + OsString::from("evm-custom"), + OsString::from("--rpc-url"), + OsString::from("http://localhost:8545/"), + OsString::from("--payment-token-address"), + OsString::from("0x5FbDB2315678afecb367f032d93F642f64180aa3"), + OsString::from("--data-payments-address"), + OsString::from("0x8464135c8F25Da09e49BC8782676a84730C318bC"), + ], + autostart: false, + contents: None, + environment: None, + label: "antnode1".parse()?, + program: node_data_dir + .to_path_buf() + .join("antnode1") + .join(ANTNODE_FILE_NAME), + username: Some(get_username()), + working_directory: None, + }), + eq(false), + ) + .returning(|_, _| Ok(())) + .in_sequence(&mut seq); + + add_node( + AddNodeServiceOptions { + auto_restart: false, + auto_set_nat_flags: false, + count: None, + delete_antnode_src: true, + enable_metrics_server: false, + env_variables: None, + home_network: false, + log_format: None, + max_archived_log_files: None, + max_log_files: None, + metrics_port: None, + network_id: Some(5), + node_ip: None, + node_port: None, + owner: None, + peers_args: Default::default(), + rpc_address: None, + rpc_port: None, + antnode_dir_path: temp_dir.to_path_buf(), + antnode_src_path: antnode_download_path.to_path_buf(), + service_data_dir_path: node_data_dir.to_path_buf(), + service_log_dir_path: node_logs_dir.to_path_buf(), + upnp: false, + user: Some(get_username()), + user_mode: false, + version: latest_version.to_string(), + evm_network: EvmNetwork::Custom(CustomNetwork { + rpc_url_http: "http://localhost:8545".parse()?, + payment_token_address: RewardsAddress::from_str( + "0x5FbDB2315678afecb367f032d93F642f64180aa3", + )?, + data_payments_address: RewardsAddress::from_str( + "0x8464135c8F25Da09e49BC8782676a84730C318bC", + )?, + }), + rewards_address: RewardsAddress::from_str( + "0x03B770D9cD32077cC0bF330c13C114a87643B124", + )?, + }, + &mut node_registry, + &mock_service_control, + VerbosityLevel::Normal, + ) + .await?; + + antnode_download_path.assert(predicate::path::missing()); + node_data_dir.assert(predicate::path::is_dir()); + node_logs_dir.assert(predicate::path::is_dir()); + assert_eq!(node_registry.nodes.len(), 1); + assert_eq!(node_registry.nodes[0].version, latest_version); + assert_eq!(node_registry.nodes[0].network_id, Some(5)); + + Ok(()) +} + #[tokio::test] async fn add_node_should_use_custom_ip() -> Result<()> { let tmp_data_dir = assert_fs::TempDir::new()?; @@ -2252,6 +2415,7 @@ async fn add_node_should_use_custom_ip() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: Some(custom_ip), node_port: None, owner: None, @@ -2348,6 +2512,7 @@ async fn add_node_should_use_custom_ports_for_one_service() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: Some(custom_port), @@ -2384,6 +2549,7 @@ async fn add_node_should_use_custom_ports_for_one_service() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(PortRange::Single(custom_port)), owner: None, @@ -2641,6 +2807,7 @@ async fn add_node_should_use_a_custom_port_range() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(PortRange::Range(12000, 12002)), owner: None, @@ -2715,6 +2882,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_port_is_used() -> R max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(12000), number: 1, @@ -2760,6 +2928,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_port_is_used() -> R max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(PortRange::Single(12000)), owner: None, @@ -2832,6 +3001,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_port_in_range_is_us max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(12000), owner: None, @@ -2877,6 +3047,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_port_in_range_is_us max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(PortRange::Range(12000, 12002)), owner: None, @@ -2955,6 +3126,7 @@ async fn add_node_should_return_an_error_if_port_and_node_count_do_not_match() - max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(PortRange::Range(12000, 12002)), owner: None, @@ -3038,6 +3210,7 @@ async fn add_node_should_return_an_error_if_multiple_services_are_specified_with max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: Some(PortRange::Single(12000)), owner: None, @@ -3183,6 +3356,7 @@ async fn add_node_should_set_random_ports_if_enable_metrics_server_is_true() -> max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -3320,6 +3494,7 @@ async fn add_node_should_set_max_archived_log_files() -> Result<()> { max_archived_log_files: Some(20), max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -3458,6 +3633,7 @@ async fn add_node_should_set_max_log_files() -> Result<()> { max_archived_log_files: None, max_log_files: Some(20), metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -3710,6 +3886,7 @@ async fn add_node_should_use_a_custom_port_range_for_metrics_server() -> Result< max_archived_log_files: None, max_log_files: None, metrics_port: Some(PortRange::Range(12000, 12002)), + network_id: None, node_ip: None, node_port: None, owner: None, @@ -3781,6 +3958,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_metrics_port_is_use max_archived_log_files: None, max_log_files: None, metrics_port: Some(12000), + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3826,6 +4004,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_metrics_port_is_use max_archived_log_files: None, max_log_files: None, metrics_port: Some(PortRange::Single(12000)), + network_id: None, node_ip: None, node_port: None, owner: None, @@ -3899,6 +4078,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_metrics_port_in_ran max_archived_log_files: None, max_log_files: None, metrics_port: Some(12000), + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3944,6 +4124,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_metrics_port_in_ran max_archived_log_files: None, max_log_files: None, metrics_port: Some(PortRange::Range(12000, 12002)), + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4179,6 +4360,7 @@ async fn add_node_should_use_a_custom_port_range_for_the_rpc_server() -> Result< max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4261,6 +4443,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_rpc_port_is_used() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -4306,6 +4489,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_rpc_port_is_used() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4379,6 +4563,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_rpc_port_in_range_i max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -4424,6 +4609,7 @@ async fn add_node_should_return_an_error_if_duplicate_custom_rpc_port_in_range_i max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4518,6 +4704,7 @@ async fn add_node_should_disable_upnp_and_home_network_if_nat_status_is_public() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -4553,6 +4740,7 @@ async fn add_node_should_disable_upnp_and_home_network_if_nat_status_is_public() max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4644,6 +4832,7 @@ async fn add_node_should_enable_upnp_if_nat_status_is_upnp() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -4679,6 +4868,7 @@ async fn add_node_should_enable_upnp_if_nat_status_is_upnp() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4770,6 +4960,7 @@ async fn add_node_should_enable_home_network_if_nat_status_is_private() -> Resul max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -4805,6 +4996,7 @@ async fn add_node_should_enable_home_network_if_nat_status_is_private() -> Resul max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4891,6 +5083,7 @@ async fn add_node_should_return_an_error_if_nat_status_is_none_but_auto_set_nat_ max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -5511,6 +5704,7 @@ async fn add_node_should_not_delete_the_source_binary_if_path_arg_is_used() -> R max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -5547,6 +5741,7 @@ async fn add_node_should_not_delete_the_source_binary_if_path_arg_is_used() -> R max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -5639,6 +5834,7 @@ async fn add_node_should_apply_the_home_network_flag_if_it_is_used() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -5675,6 +5871,7 @@ async fn add_node_should_apply_the_home_network_flag_if_it_is_used() -> Result<( max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -5767,6 +5964,7 @@ async fn add_node_should_add_the_node_in_user_mode() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -5803,6 +6001,7 @@ async fn add_node_should_add_the_node_in_user_mode() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -5892,6 +6091,7 @@ async fn add_node_should_add_the_node_with_upnp_enabled() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, name: "antnode1".to_string(), node_ip: None, node_port: None, @@ -5928,6 +6128,7 @@ async fn add_node_should_add_the_node_with_upnp_enabled() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -6064,6 +6265,7 @@ async fn add_node_should_assign_an_owner_in_lowercase() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: Some("Discord_Username".to_string()), @@ -6202,6 +6404,7 @@ async fn add_node_should_auto_restart() -> Result<()> { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: Some("discord_username".to_string()), diff --git a/ant-node-manager/src/bin/cli/main.rs b/ant-node-manager/src/bin/cli/main.rs index 5e6afa325c..b440cb09d8 100644 --- a/ant-node-manager/src/bin/cli/main.rs +++ b/ant-node-manager/src/bin/cli/main.rs @@ -172,6 +172,11 @@ pub enum SubCmd { /// services, which in this case would be 5. The range must also go from lower to higher. #[clap(long, value_parser = PortRange::parse)] metrics_port: Option, + /// Specify the network ID to use for the services. This will allow you to run the node on a different network. + /// + /// By default, the network ID is set to 1, which represents the mainnet. + #[clap(long, verbatim_doc_comment)] + network_id: Option, /// Specify the IP address for the antnode service(s). /// /// If not set, we bind to all the available network interfaces. @@ -1075,6 +1080,7 @@ async fn main() -> Result<()> { max_archived_log_files, max_log_files, metrics_port, + network_id, node_ip, node_port, owner, @@ -1102,6 +1108,7 @@ async fn main() -> Result<()> { max_archived_log_files, max_log_files, metrics_port, + network_id, node_ip, node_port, owner, diff --git a/ant-node-manager/src/cmd/node.rs b/ant-node-manager/src/cmd/node.rs index fd4b938bbc..5ab42c0ea8 100644 --- a/ant-node-manager/src/cmd/node.rs +++ b/ant-node-manager/src/cmd/node.rs @@ -49,6 +49,7 @@ pub async fn add( max_archived_log_files: Option, max_log_files: Option, metrics_port: Option, + network_id: Option, node_ip: Option, node_port: Option, owner: Option, @@ -125,6 +126,7 @@ pub async fn add( max_archived_log_files, max_log_files, metrics_port, + network_id, node_ip, node_port, owner, @@ -593,6 +595,7 @@ pub async fn maintain_n_running_nodes( max_archived_log_files: Option, max_log_files: Option, metrics_port: Option, + network_id: Option, node_ip: Option, node_port: Option, owner: Option, @@ -697,6 +700,7 @@ pub async fn maintain_n_running_nodes( max_archived_log_files, max_log_files, metrics_port.clone(), + network_id, node_ip, Some(PortRange::Single(port)), owner.clone(), diff --git a/ant-node-manager/src/lib.rs b/ant-node-manager/src/lib.rs index 2b4c6a8921..8b2aaee95b 100644 --- a/ant-node-manager/src/lib.rs +++ b/ant-node-manager/src/lib.rs @@ -767,6 +767,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -880,6 +881,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -958,6 +960,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1076,6 +1079,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1167,6 +1171,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1268,6 +1273,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1368,6 +1374,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1438,6 +1445,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1500,6 +1508,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1560,6 +1569,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1623,6 +1633,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1697,6 +1708,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1836,6 +1848,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -1936,6 +1949,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -2081,6 +2095,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -2238,6 +2253,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -2390,6 +2406,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -2543,6 +2560,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -2721,6 +2739,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -2892,6 +2911,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, +network_id: None, node_ip: None, node_port: None, number: 1, @@ -2954,6 +2974,168 @@ mod tests { Ok(()) } + #[tokio::test] + async fn upgrade_should_retain_the_network_id_arg() -> Result<()> { + let current_version = "0.1.0"; + let target_version = "0.2.0"; + + let tmp_data_dir = assert_fs::TempDir::new()?; + let current_install_dir = tmp_data_dir.child("antnode_install"); + current_install_dir.create_dir_all()?; + + let current_node_bin = current_install_dir.child("antnode"); + current_node_bin.write_binary(b"fake antnode binary")?; + let target_node_bin = tmp_data_dir.child("antnode"); + target_node_bin.write_binary(b"fake antnode binary")?; + + let mut mock_service_control = MockServiceControl::new(); + let mut mock_rpc_client = MockRpcClient::new(); + + // before binary upgrade + mock_service_control + .expect_get_process_pid() + .with(eq(current_node_bin.to_path_buf().clone())) + .times(1) + .returning(|_| Ok(1000)); + mock_service_control + .expect_stop() + .with(eq("antnode1"), eq(false)) + .times(1) + .returning(|_, _| Ok(())); + + // after binary upgrade + mock_service_control + .expect_uninstall() + .with(eq("antnode1"), eq(false)) + .times(1) + .returning(|_, _| Ok(())); + mock_service_control + .expect_install() + .with( + eq(ServiceInstallCtx { + args: vec![ + OsString::from("--rpc"), + OsString::from("127.0.0.1:8081"), + OsString::from("--root-dir"), + OsString::from("/var/antctl/services/antnode1"), + OsString::from("--log-output-dest"), + OsString::from("/var/log/antnode/antnode1"), + OsString::from("--network-id"), + OsString::from("5"), + OsString::from("--rewards-address"), + OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"), + OsString::from("evm-arbitrum-one"), + ], + autostart: false, + contents: None, + environment: None, + label: "antnode1".parse()?, + program: current_node_bin.to_path_buf(), + username: Some("ant".to_string()), + working_directory: None, + }), + eq(false), + ) + .times(1) + .returning(|_, _| Ok(())); + + // after service restart + mock_service_control + .expect_start() + .with(eq("antnode1"), eq(false)) + .times(1) + .returning(|_, _| Ok(())); + mock_service_control + .expect_wait() + .with(eq(3000)) + .times(1) + .returning(|_| ()); + mock_service_control + .expect_get_process_pid() + .with(eq(current_node_bin.to_path_buf().clone())) + .times(1) + .returning(|_| Ok(100)); + + mock_rpc_client.expect_node_info().times(1).returning(|| { + Ok(NodeInfo { + pid: 2000, + peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?, + data_path: PathBuf::from("/var/antctl/services/antnode1"), + log_path: PathBuf::from("/var/log/antnode/antnode1"), + version: target_version.to_string(), + uptime: std::time::Duration::from_secs(1), // the service was just started + wallet_balance: 0, + }) + }); + mock_rpc_client + .expect_network_info() + .times(1) + .returning(|| { + Ok(NetworkInfo { + connected_peers: Vec::new(), + listeners: Vec::new(), + }) + }); + + let mut service_data = NodeServiceData { + auto_restart: false, + connected_peers: None, + data_dir_path: PathBuf::from("/var/antctl/services/antnode1"), + evm_network: EvmNetwork::ArbitrumOne, + home_network: false, + listen_addr: None, + log_dir_path: PathBuf::from("/var/log/antnode/antnode1"), + log_format: None, + max_archived_log_files: None, + max_log_files: None, + metrics_port: None, + network_id: Some(5), + node_ip: None, + node_port: None, + number: 1, + owner: None, + peer_id: Some(PeerId::from_str( + "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR", + )?), + peers_args: Default::default(), + pid: Some(1000), + rewards_address: RewardsAddress::from_str( + "0x03B770D9cD32077cC0bF330c13C114a87643B124", + )?, + reward_balance: Some(AttoTokens::zero()), + rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081), + antnode_path: current_node_bin.to_path_buf(), + service_name: "antnode1".to_string(), + status: ServiceStatus::Running, + upnp: false, + user: Some("ant".to_string()), + user_mode: false, + version: current_version.to_string(), + }; + let service = NodeService::new(&mut service_data, Box::new(mock_rpc_client)); + + let mut service_manager = ServiceManager::new( + service, + Box::new(mock_service_control), + VerbosityLevel::Normal, + ); + + service_manager + .upgrade(UpgradeOptions { + auto_restart: false, + env_variables: None, + force: false, + start_service: true, + target_bin_path: target_node_bin.to_path_buf(), + target_version: Version::parse(target_version).unwrap(), + }) + .await?; + + assert_eq!(service_manager.service.service_data.network_id, Some(5)); + + Ok(()) + } + #[tokio::test] async fn upgrade_should_retain_the_local_flag() -> Result<()> { let current_version = "0.1.0"; @@ -3068,6 +3250,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3237,6 +3420,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3416,6 +3600,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3590,6 +3775,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3759,6 +3945,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -3938,6 +4125,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -4099,6 +4287,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, owner: None, @@ -4263,6 +4452,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -4424,6 +4614,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, number: 1, node_ip: Some(Ipv4Addr::new(192, 168, 1, 1)), node_port: None, @@ -4588,6 +4779,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, number: 1, node_ip: None, node_port: Some(12000), @@ -4748,6 +4940,7 @@ mod tests { max_archived_log_files: Some(20), max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -4912,6 +5105,7 @@ mod tests { max_archived_log_files: None, max_log_files: Some(20), metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -5074,6 +5268,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: Some(12000), + network_id: None, node_ip: None, node_port: None, number: 1, @@ -5238,6 +5433,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: Some(12000), + network_id: None, node_ip: None, node_port: None, number: 1, @@ -5402,6 +5598,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -5566,6 +5763,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -5741,6 +5939,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -5917,6 +6116,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -6081,6 +6281,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -6165,6 +6366,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -6233,6 +6435,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -6316,6 +6519,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -6394,6 +6598,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, @@ -6470,6 +6675,7 @@ mod tests { max_archived_log_files: None, max_log_files: None, metrics_port: None, + network_id: None, node_ip: None, node_port: None, number: 1, diff --git a/ant-node-manager/src/local.rs b/ant-node-manager/src/local.rs index 9bfc06eee9..6acd1d6531 100644 --- a/ant-node-manager/src/local.rs +++ b/ant-node-manager/src/local.rs @@ -435,6 +435,7 @@ pub async fn run_node( max_archived_log_files: None, max_log_files: None, metrics_port: run_options.metrics_port, + network_id: None, node_ip: None, node_port: run_options.node_port, number: run_options.number, diff --git a/ant-node-manager/src/rpc.rs b/ant-node-manager/src/rpc.rs index a06d0ef338..1af38833ff 100644 --- a/ant-node-manager/src/rpc.rs +++ b/ant-node-manager/src/rpc.rs @@ -74,6 +74,7 @@ pub async fn restart_node_service( max_log_files: current_node_clone.max_log_files, metrics_port: None, name: current_node_clone.service_name.clone(), + network_id: current_node_clone.network_id, node_ip: current_node_clone.node_ip, node_port: current_node_clone.get_antnode_port(), owner: current_node_clone.owner.clone(), @@ -189,6 +190,7 @@ pub async fn restart_node_service( max_archived_log_files: current_node_clone.max_archived_log_files, max_log_files: current_node_clone.max_log_files, metrics_port: None, + network_id: current_node_clone.network_id, node_ip: current_node_clone.node_ip, node_port: None, owner: None, @@ -217,6 +219,7 @@ pub async fn restart_node_service( max_archived_log_files: current_node_clone.max_archived_log_files, max_log_files: current_node_clone.max_log_files, metrics_port: None, + network_id: current_node_clone.network_id, node_ip: current_node_clone.node_ip, node_port: None, number: new_node_number as u16, diff --git a/ant-node/src/bin/antnode/main.rs b/ant-node/src/bin/antnode/main.rs index ec8d759f7b..db40d00101 100644 --- a/ant-node/src/bin/antnode/main.rs +++ b/ant-node/src/bin/antnode/main.rs @@ -22,7 +22,7 @@ use ant_node::{Marker, NodeBuilder, NodeEvent, NodeEventsReceiver}; use ant_protocol::{ node::get_antnode_root_dir, node_rpc::{NodeCtrl, StopResult}, - version::IDENTIFY_PROTOCOL_STR, + version, }; use clap::{command, Parser}; use color_eyre::{eyre::eyre, Result}; @@ -128,6 +128,12 @@ struct Opt { #[clap(long, verbatim_doc_comment)] max_archived_log_files: Option, + /// Specify the network ID to use. This will allow you to run the node on a different network. + /// + /// By default, the network ID is set to 1, which represents the mainnet. + #[clap(long, verbatim_doc_comment)] + network_id: Option, + /// Specify the rewards address. /// The rewards address is the address that will receive the rewards for the node. /// It should be a valid EVM address. @@ -217,13 +223,20 @@ fn main() -> Result<()> { color_eyre::install()?; let opt = Opt::parse(); + if let Some(network_id) = opt.network_id { + version::set_network_id(network_id); + } + + let identify_protocol_str = version::IDENTIFY_PROTOCOL_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_PROTOCOL_STR"); if opt.version { println!( "{}", ant_build_info::version_string( "Autonomi Node", env!("CARGO_PKG_VERSION"), - Some(&IDENTIFY_PROTOCOL_STR) + Some(&identify_protocol_str) ) ); return Ok(()); @@ -240,7 +253,7 @@ fn main() -> Result<()> { } if opt.protocol_version { - println!("Network version: {}", *IDENTIFY_PROTOCOL_STR); + println!("Network version: {identify_protocol_str}"); return Ok(()); } @@ -279,7 +292,7 @@ fn main() -> Result<()> { ); info!("\n{}\n{}", msg, "=".repeat(msg.len())); - ant_build_info::log_version_info(env!("CARGO_PKG_VERSION"), &IDENTIFY_PROTOCOL_STR); + ant_build_info::log_version_info(env!("CARGO_PKG_VERSION"), &identify_protocol_str); debug!( "antnode built with git version: {}", ant_build_info::git_info() diff --git a/ant-protocol/src/version.rs b/ant-protocol/src/version.rs index 6606e74be0..3d5c92cfab 100644 --- a/ant-protocol/src/version.rs +++ b/ant-protocol/src/version.rs @@ -7,39 +7,83 @@ // permissions and limitations relating to use of the SAFE Network Software. use lazy_static::lazy_static; +use std::sync::RwLock; lazy_static! { + /// The network_id is used to differentiate between different networks. + /// The default is set to 1 and it represents the mainnet. + pub static ref NETWORK_ID: RwLock = RwLock::new(1); + /// The node version used during Identify Behaviour. - pub static ref IDENTIFY_NODE_VERSION_STR: String = - format!( - "safe/node/{}/{}", + pub static ref IDENTIFY_NODE_VERSION_STR: RwLock = + RwLock::new(format!( + "ant/node/{}/{}", get_truncate_version_str(), - get_key_version_str(), - ); + *NETWORK_ID.read().expect("Failed to obtain read lock for NETWORK_ID"), + )); /// The client version used during Identify Behaviour. - pub static ref IDENTIFY_CLIENT_VERSION_STR: String = - format!( - "safe/client/{}/{}", + pub static ref IDENTIFY_CLIENT_VERSION_STR: RwLock = + RwLock::new(format!( + "ant/client/{}/{}", get_truncate_version_str(), - get_key_version_str(), - ); + *NETWORK_ID.read().expect("Failed to obtain read lock for NETWORK_ID"), + )); /// The req/response protocol version - pub static ref REQ_RESPONSE_VERSION_STR: String = - format!( - "/safe/node/{}/{}", + pub static ref REQ_RESPONSE_VERSION_STR: RwLock = + RwLock::new(format!( + "/ant/{}/{}", get_truncate_version_str(), - get_key_version_str(), - ); + *NETWORK_ID.read().expect("Failed to obtain read lock for NETWORK_ID"), + )); /// The identify protocol version - pub static ref IDENTIFY_PROTOCOL_STR: String = - format!( - "safe/{}/{}", + pub static ref IDENTIFY_PROTOCOL_STR: RwLock = + RwLock::new(format!( + "ant/{}/{}", get_truncate_version_str(), - get_key_version_str(), - ); + *NETWORK_ID.read().expect("Failed to obtain read lock for NETWORK_ID"), + )); +} + +/// Update the NETWORK_ID and all the version strings that depend on it. +/// By default, the network id is set to 1 which represents the mainnet. +/// +/// This should be called before starting the node or client. +/// The values will be read often and this can cause issues if the values are changed after the node is started. +pub fn set_network_id(id: u8) { + let mut network_id = NETWORK_ID + .write() + .expect("Failed to obtain write lock for NETWORK_ID"); + *network_id = id; + + let mut node_version = IDENTIFY_NODE_VERSION_STR + .write() + .expect("Failed to obtain write lock for IDENTIFY_NODE_VERSION_STR"); + *node_version = format!("ant/node/{}/{}", get_truncate_version_str(), id); + let mut client_version = IDENTIFY_CLIENT_VERSION_STR + .write() + .expect("Failed to obtain write lock for IDENTIFY_CLIENT_VERSION_STR"); + *client_version = format!("ant/client/{}/{}", get_truncate_version_str(), id); + let mut req_response_version = REQ_RESPONSE_VERSION_STR + .write() + .expect("Failed to obtain write lock for REQ_RESPONSE_VERSION_STR"); + *req_response_version = format!("/ant/{}/{}", get_truncate_version_str(), id); + let mut identify_protocol = IDENTIFY_PROTOCOL_STR + .write() + .expect("Failed to obtain write lock for IDENTIFY_PROTOCOL_STR"); + *identify_protocol = format!("ant/{}/{}", get_truncate_version_str(), id); +} + +/// Get the current NETWORK_ID as string. +pub fn get_network_id() -> String { + format!( + "{}", + *NETWORK_ID + .read() + .expect("Failed to obtain read lock for NETWORK_ID") + ) } // Protocol support shall be downward compatible for patch only version update. @@ -54,42 +98,44 @@ pub fn get_truncate_version_str() -> String { } } -/// FIXME: Remove this once BEFORE next breaking release and fix this whole file -/// Get the PKs version string. -/// If the public key mis-configed via env variable, -/// it shall result in being rejected to join by the network -pub fn get_key_version_str() -> String { - // let mut f_k_str = FOUNDATION_PK.to_hex(); - // let _ = f_k_str.split_off(6); - // let mut g_k_str = GENESIS_PK.to_hex(); - // let _ = g_k_str.split_off(6); - // let mut n_k_str = NETWORK_ROYALTIES_PK.to_hex(); - // let _ = n_k_str.split_off(6); - // let s = format!("{f_k_str}_{g_k_str}_{n_k_str}"); - // dbg!(&s); - "b20c91_93f735_af451a".to_string() -} #[cfg(test)] mod tests { use super::*; #[test] fn test_print_version_strings() -> Result<(), Box> { - // Test and print all version strings println!( - "\nIDENTIFY_CLIENT_VERSION_STR: {}", + "\nIDENTIFY_NODE_VERSION_STR: {}", + *IDENTIFY_NODE_VERSION_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_NODE_VERSION_STR") + ); + println!( + "IDENTIFY_CLIENT_VERSION_STR: {}", *IDENTIFY_CLIENT_VERSION_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_CLIENT_VERSION_STR") + ); + println!( + "REQ_RESPONSE_VERSION_STR: {}", + *REQ_RESPONSE_VERSION_STR + .read() + .expect("Failed to obtain read lock for REQ_RESPONSE_VERSION_STR") + ); + println!( + "IDENTIFY_PROTOCOL_STR: {}", + *IDENTIFY_PROTOCOL_STR + .read() + .expect("Failed to obtain read lock for IDENTIFY_PROTOCOL_STR") ); - println!("REQ_RESPONSE_VERSION_STR: {}", *REQ_RESPONSE_VERSION_STR); - println!("IDENTIFY_PROTOCOL_STR: {}", *IDENTIFY_PROTOCOL_STR); // Test truncated version string let truncated = get_truncate_version_str(); println!("\nTruncated version: {truncated}"); - // Test key version string - let key_version = get_key_version_str(); - println!("\nKey version string: {key_version}"); + // Test network id string + let network_id = get_network_id(); + println!("Network ID string: {network_id}"); Ok(()) } diff --git a/ant-service-management/src/node.rs b/ant-service-management/src/node.rs index d9a91eeb12..3c281ba4b7 100644 --- a/ant-service-management/src/node.rs +++ b/ant-service-management/src/node.rs @@ -77,6 +77,10 @@ impl ServiceStateActions for NodeService<'_> { args.push(OsString::from("--log-format")); args.push(OsString::from(log_fmt.as_str())); } + if let Some(id) = self.service_data.network_id { + args.push(OsString::from("--network-id")); + args.push(OsString::from(id.to_string())); + } if self.service_data.upnp { args.push(OsString::from("--upnp")); } @@ -286,6 +290,7 @@ pub struct NodeServiceData { pub metrics_port: Option, #[serde(default)] pub owner: Option, + pub network_id: Option, #[serde(default)] pub node_ip: Option, #[serde(default)] diff --git a/autonomi/src/client/mod.rs b/autonomi/src/client/mod.rs index acc62981da..d14964f9f1 100644 --- a/autonomi/src/client/mod.rs +++ b/autonomi/src/client/mod.rs @@ -177,7 +177,7 @@ async fn handle_event_receiver( sender .send(Err(ConnectError::TimedOutWithIncompatibleProtocol( protocols, - IDENTIFY_PROTOCOL_STR.to_string(), + IDENTIFY_PROTOCOL_STR.read().expect("Failed to obtain read lock for IDENTIFY_PROTOCOL_STR. A call to set_network_id performed. This should not happen").clone(), ))) .expect("receiver should not close"); } else { diff --git a/node-launchpad/src/node_mgmt.rs b/node-launchpad/src/node_mgmt.rs index daad00123f..735f049fea 100644 --- a/node-launchpad/src/node_mgmt.rs +++ b/node-launchpad/src/node_mgmt.rs @@ -424,6 +424,7 @@ async fn scale_down_nodes(config: &NodeConfig, count: u16) { None, None, None, + None, None, // We don't care about the port, as we are scaling down config.owner.clone(), config.peers_args.clone(), @@ -497,6 +498,7 @@ async fn add_nodes( None, None, None, + None, port_range, config.owner.clone(), config.peers_args.clone(),