From c81344290068498d99e804e400a0cdca9b4ae216 Mon Sep 17 00:00:00 2001 From: Roland Sherwin Date: Mon, 1 Jul 2024 12:57:20 +0530 Subject: [PATCH] fix(manager): use default nat detection server list if none is provided --- Cargo.lock | 2 +- node-launchpad/Cargo.toml | 3 +- node-launchpad/src/components/home.rs | 13 ++------- sn_node_manager/Cargo.toml | 1 + sn_node_manager/src/bin/cli/main.rs | 7 +++-- sn_node_manager/src/cmd/nat_detection.rs | 18 +++++++++++- sn_peers_acquisition/Cargo.toml | 10 +++---- sn_peers_acquisition/src/error.rs | 4 +-- sn_peers_acquisition/src/lib.rs | 35 +++++++++++------------- 9 files changed, 48 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c82f4972be..53704a25fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4696,7 +4696,6 @@ dependencies = [ "log", "pretty_assertions", "prometheus-parse", - "rand 0.8.5", "ratatui", "reqwest 0.12.4", "serde", @@ -6936,6 +6935,7 @@ dependencies = [ "nix 0.27.1", "predicates 3.1.0", "prost 0.9.0", + "rand 0.8.5", "reqwest 0.12.4", "semver", "serde", diff --git a/node-launchpad/Cargo.toml b/node-launchpad/Cargo.toml index 5299a3bffb..1d04807df4 100644 --- a/node-launchpad/Cargo.toml +++ b/node-launchpad/Cargo.toml @@ -42,7 +42,6 @@ libc = "0.2.148" log = "0.4.20" pretty_assertions = "1.4.0" prometheus-parse = "0.2.5" -rand = "0.8.5" ratatui = { version = "0.26.0", features = ["serde", "macros", "unstable-widget-ref"] } reqwest = { version = "0.12.2", default-features = false, features = [ "rustls-tls-manual-roots", @@ -51,7 +50,7 @@ serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" signal-hook = "0.3.17" sn-node-manager = { version = "0.9.7", path = "../sn_node_manager" } -sn_peers_acquisition = { version = "0.3.5", path = "../sn_peers_acquisition", features = ["network-contacts"]} +sn_peers_acquisition = { version = "0.3.5", path = "../sn_peers_acquisition" } sn-releases = "~0.2.6" sn_service_management = { version = "0.3.7", path = "../sn_service_management" } strip-ansi-escapes = "0.2.0" diff --git a/node-launchpad/src/components/home.rs b/node-launchpad/src/components/home.rs index f0bc1007b1..ad1078e135 100644 --- a/node-launchpad/src/components/home.rs +++ b/node-launchpad/src/components/home.rs @@ -18,10 +18,9 @@ use crate::{ }, }; use color_eyre::eyre::{OptionExt, Result}; -use rand::seq::SliceRandom; use ratatui::{prelude::*, widgets::*}; use sn_node_manager::{config::get_node_registry_path, VerbosityLevel}; -use sn_peers_acquisition::{get_bootstrap_peers_from_url, PeersArgs}; +use sn_peers_acquisition::PeersArgs; use sn_service_management::{ control::ServiceController, NodeRegistry, NodeServiceData, ServiceStatus, }; @@ -34,8 +33,6 @@ use tokio::sync::mpsc::UnboundedSender; const NODE_START_INTERVAL: usize = 10; const NODE_STAT_UPDATE_INTERVAL: Duration = Duration::from_secs(5); -const NAT_DETECTION_SERVERS_LIST_URL: &str = - "https://sn-testnet.s3.eu-west-2.amazonaws.com/nat-detection-servers"; /// If nat detection fails for more than 3 times, we don't want to waste time running during every node start. const MAX_ERRORS_WHILE_RUNNING_NAT_DETECTION: usize = 3; @@ -613,14 +610,8 @@ fn stop_nodes(services: Vec, action_sender: UnboundedSender) { } async fn run_nat_detection_process() -> Result<()> { - let servers = get_bootstrap_peers_from_url(NAT_DETECTION_SERVERS_LIST_URL.parse()?).await?; - let servers = servers - .choose_multiple(&mut rand::thread_rng(), 10) - .cloned() - .collect::>(); - info!("Running nat detection with servers: {servers:?}"); sn_node_manager::cmd::nat_detection::run_nat_detection( - servers, + None, true, None, None, diff --git a/sn_node_manager/Cargo.toml b/sn_node_manager/Cargo.toml index 5e877cbc6d..8159f0b502 100644 --- a/sn_node_manager/Cargo.toml +++ b/sn_node_manager/Cargo.toml @@ -39,6 +39,7 @@ indicatif = { version = "0.17.5", features = ["tokio"] } libp2p = { version = "0.53", features = [] } libp2p-identity = { version = "0.2.7", features = ["rand"] } prost = { version = "0.9" } +rand = "0.8.5" semver = "1.0.20" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/sn_node_manager/src/bin/cli/main.rs b/sn_node_manager/src/bin/cli/main.rs index 804edbd30e..4598ea8f4d 100644 --- a/sn_node_manager/src/bin/cli/main.rs +++ b/sn_node_manager/src/bin/cli/main.rs @@ -673,13 +673,14 @@ pub enum NatDetectionSubCmd { /// Useful for running NAT detection using a custom built binary. #[clap(long)] path: Option, - /// Provide NAT servers in the form of a multiaddr or an address/port pair. + /// Provide NAT servers in the form of a multiaddr or an address/port pair. If no servers are provided, + /// the default servers will be used. /// /// We attempt to establish connections to these servers to determine our own NAT status. /// /// The argument can be used multiple times. - #[clap(long, required = true, value_delimiter = ',')] - servers: Vec, + #[clap(long, value_delimiter = ',')] + servers: Option>, /// Provide a NAT detection binary using a URL. /// /// The binary must be inside a zip or gzipped tar archive. diff --git a/sn_node_manager/src/cmd/nat_detection.rs b/sn_node_manager/src/cmd/nat_detection.rs index 044395f7ad..1feed7f481 100644 --- a/sn_node_manager/src/cmd/nat_detection.rs +++ b/sn_node_manager/src/cmd/nat_detection.rs @@ -11,6 +11,8 @@ use crate::{ }; use color_eyre::eyre::{bail, OptionExt, Result}; use libp2p::Multiaddr; +use rand::seq::SliceRandom; +use sn_peers_acquisition::get_peers_from_url; use sn_releases::{ReleaseType, SafeReleaseRepoActions}; use sn_service_management::{NatDetectionStatus, NodeRegistry}; use std::{ @@ -19,14 +21,28 @@ use std::{ process::{Command, Stdio}, }; +const NAT_DETECTION_SERVERS_LIST_URL: &str = + "https://sn-testnet.s3.eu-west-2.amazonaws.com/nat-detection-servers"; + pub async fn run_nat_detection( - servers: Vec, + servers: Option>, force_run: bool, path: Option, url: Option, version: Option, verbosity: VerbosityLevel, ) -> Result<()> { + let servers = match servers { + Some(servers) => servers, + None => { + let servers = get_peers_from_url(NAT_DETECTION_SERVERS_LIST_URL.parse()?).await?; + + servers + .choose_multiple(&mut rand::thread_rng(), 10) + .cloned() + .collect::>() + } + }; info!("Running nat detection with servers: {servers:?}"); let mut node_registry = NodeRegistry::load(&get_node_registry_path()?)?; diff --git a/sn_peers_acquisition/Cargo.toml b/sn_peers_acquisition/Cargo.toml index 35622dbbc6..c86cc6ad13 100644 --- a/sn_peers_acquisition/Cargo.toml +++ b/sn_peers_acquisition/Cargo.toml @@ -12,7 +12,7 @@ version = "0.3.5" [features] local-discovery = [] -network-contacts = ["reqwest", "tokio", "url"] +network-contacts = ["sn_networking"] websockets = [] [dependencies] @@ -20,12 +20,12 @@ clap = { version = "4.2.1", features = ["derive", "env"] } lazy_static = "~1.4.0" libp2p = { version="0.53", features = [] } rand = "0.8.5" -reqwest = { version="0.12.2", default-features=false, features = ["rustls-tls"], optional = true } -sn_networking = { path = "../sn_networking", version = "0.16.6" } +reqwest = { version="0.12.2", default-features=false, features = ["rustls-tls"] } +sn_networking = { path = "../sn_networking", version = "0.16.6", optional = true} thiserror = "1.0.23" -tokio = { version = "1.32.0", optional = true, default-features = false} +tokio = { version = "1.32.0", default-features = false} tracing = { version = "~0.1.26" } -url = { version = "2.4.0", optional = true } +url = { version = "2.4.0" } [lints] workspace = true diff --git a/sn_peers_acquisition/src/error.rs b/sn_peers_acquisition/src/error.rs index 9f3fec99eb..03370d6657 100644 --- a/sn_peers_acquisition/src/error.rs +++ b/sn_peers_acquisition/src/error.rs @@ -8,15 +8,13 @@ pub enum Error { #[error("Could not parse the supplied multiaddr or socket address")] InvalidPeerAddr, #[error("Could not obtain network contacts from {0} after {1} retries")] - NetworkContactsUnretrievable(String, usize), + FailedToObtainPeersFromUrl(String, usize), #[error("No valid multaddr was present in the contacts file at {0}")] NoMultiAddrObtainedFromNetworkContacts(String), #[error("Could not obtain peers through any available options")] PeersNotObtained, - #[cfg(feature = "network-contacts")] #[error(transparent)] ReqwestError(#[from] reqwest::Error), - #[cfg(feature = "network-contacts")] #[error(transparent)] UrlParseError(#[from] url::ParseError), } diff --git a/sn_peers_acquisition/src/lib.rs b/sn_peers_acquisition/src/lib.rs index afcd3ec512..0b8453d34f 100644 --- a/sn_peers_acquisition/src/lib.rs +++ b/sn_peers_acquisition/src/lib.rs @@ -17,7 +17,6 @@ use rand::{seq::SliceRandom, thread_rng}; #[cfg(feature = "network-contacts")] use sn_networking::version::get_network_version; use tracing::*; -#[cfg(feature = "network-contacts")] use url::Url; #[cfg(feature = "network-contacts")] @@ -30,9 +29,8 @@ lazy_static! { }; } -#[cfg(feature = "network-contacts")] -// The maximum number of retries to be performed while trying to fetch the network contacts file. -const MAX_NETWORK_CONTACTS_GET_RETRIES: usize = 3; +// The maximum number of retries to be performed while trying to get peers from a URL. +const MAX_RETRIES_ON_GET_PEERS_FROM_URL: usize = 3; /// The name of the environment variable that can be used to pass peers to the node. pub const SAFE_PEERS_ENV: &str = "SAFE_PEERS"; @@ -154,7 +152,7 @@ impl PeersArgs { info!("Trying to fetch the bootstrap peers from {url}"); - get_bootstrap_peers_from_url(url).await + get_peers_from_url(url).await } } @@ -188,11 +186,8 @@ pub fn parse_peer_addr(addr: &str) -> Result { Err(Error::InvalidPeerAddr) } -#[cfg(feature = "network-contacts")] -/// Get bootstrap peers from the Network contacts file stored in the given URL. -/// -/// If URL is not provided, the addresses are fetched from the default NETWORK_CONTACTS_URL -pub async fn get_bootstrap_peers_from_url(url: Url) -> Result> { +/// Get and parse a list of peers from a URL. The URL should contain one multiaddr per line. +pub async fn get_peers_from_url(url: Url) -> Result> { let mut retries = 0; loop { @@ -203,7 +198,7 @@ pub async fn get_bootstrap_peers_from_url(url: Url) -> Result> { let mut multi_addresses = Vec::new(); if response.status().is_success() { let text = response.text().await?; - trace!("Got bootstrap peers from {url}: {text}"); + trace!("Got peers from url: {url}: {text}"); // example of contacts file exists in resources/network-contacts-examples for addr in text.split('\n') { // ignore empty/last lines @@ -215,7 +210,7 @@ pub async fn get_bootstrap_peers_from_url(url: Url) -> Result> { multi_addresses.push(parse_peer_addr(addr)?); } if !multi_addresses.is_empty() { - trace!("Successfully got bootstrap peers from URL {multi_addresses:?}"); + trace!("Successfully got peers from URL {multi_addresses:?}"); return Ok(multi_addresses); } else { return Err(Error::NoMultiAddrObtainedFromNetworkContacts( @@ -224,25 +219,27 @@ pub async fn get_bootstrap_peers_from_url(url: Url) -> Result> { } } else { retries += 1; - if retries >= MAX_NETWORK_CONTACTS_GET_RETRIES { - return Err(Error::NetworkContactsUnretrievable( + if retries >= MAX_RETRIES_ON_GET_PEERS_FROM_URL { + return Err(Error::FailedToObtainPeersFromUrl( url.to_string(), - MAX_NETWORK_CONTACTS_GET_RETRIES, + MAX_RETRIES_ON_GET_PEERS_FROM_URL, )); } } } Err(_) => { retries += 1; - if retries >= MAX_NETWORK_CONTACTS_GET_RETRIES { - return Err(Error::NetworkContactsUnretrievable( + if retries >= MAX_RETRIES_ON_GET_PEERS_FROM_URL { + return Err(Error::FailedToObtainPeersFromUrl( url.to_string(), - MAX_NETWORK_CONTACTS_GET_RETRIES, + MAX_RETRIES_ON_GET_PEERS_FROM_URL, )); } } } - trace!("Failed to get bootstrap peers from URL, retrying {retries}/{MAX_NETWORK_CONTACTS_GET_RETRIES}"); + trace!( + "Failed to get peers from URL, retrying {retries}/{MAX_RETRIES_ON_GET_PEERS_FROM_URL}" + ); tokio::time::sleep(std::time::Duration::from_secs(1)).await; } }