unified native, socks5, NR client inits

This commit is contained in:
Jędrzej Stuczyński
2023-10-30 16:13:05 +00:00
parent da9d743f39
commit f6f2cd7e17
29 changed files with 534 additions and 533 deletions
Generated
+27 -26
View File
@@ -1158,7 +1158,7 @@ checksum = "f769ab9e8c1652d78dd0b3ec59cdaa1e2bcb3b6b39f6681b256abcdbe101cc14"
dependencies = [
"anyhow",
"cargo_metadata",
"clap 4.4.6",
"clap 4.4.7",
"concolor-control",
"crates-index",
"dirs-next",
@@ -1393,9 +1393,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.4.6"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1403,13 +1403,13 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.4.6"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
dependencies = [
"anstream",
"anstyle",
"clap_lex 0.5.1",
"clap_lex 0.6.0",
"strsim",
"terminal_size",
]
@@ -1420,7 +1420,7 @@ version = "4.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7"
dependencies = [
"clap 4.4.6",
"clap 4.4.7",
]
[[package]]
@@ -1429,15 +1429,15 @@ version = "4.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29bdbe21a263b628f83fcbeac86a4416a1d588c7669dd41473bc4149e4e7d2f1"
dependencies = [
"clap 4.4.6",
"clap 4.4.7",
"clap_complete",
]
[[package]]
name = "clap_derive"
version = "4.4.2"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@@ -1456,9 +1456,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.5.1"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "cloudabi"
@@ -2871,7 +2871,7 @@ dependencies = [
"bytes",
"cfg-if",
"chrono",
"clap 4.4.6",
"clap 4.4.7",
"config",
"digest 0.10.7",
"dirs 5.0.1",
@@ -2941,7 +2941,7 @@ name = "explorer-api"
version = "1.1.30"
dependencies = [
"chrono",
"clap 4.4.6",
"clap 4.4.7",
"dotenvy",
"humantime-serde",
"isocountry",
@@ -5961,7 +5961,7 @@ dependencies = [
"bs58 0.4.0",
"cfg-if",
"chrono",
"clap 4.4.6",
"clap 4.4.7",
"console-subscriber",
"cosmwasm-std",
"cw-utils",
@@ -6066,7 +6066,7 @@ name = "nym-bin-common"
version = "0.6.0"
dependencies = [
"atty",
"clap 4.4.6",
"clap 4.4.7",
"clap_complete",
"clap_complete_fig",
"log",
@@ -6107,7 +6107,7 @@ dependencies = [
"base64 0.13.1",
"bip39",
"bs58 0.4.0",
"clap 4.4.6",
"clap 4.4.7",
"clap_complete",
"clap_complete_fig",
"dotenvy",
@@ -6132,7 +6132,7 @@ dependencies = [
"bip39",
"bs58 0.4.0",
"cfg-if",
"clap 4.4.6",
"clap 4.4.7",
"comfy-table",
"cosmrs",
"cosmwasm-std",
@@ -6176,7 +6176,7 @@ dependencies = [
name = "nym-client"
version = "1.1.30"
dependencies = [
"clap 4.4.6",
"clap 4.4.7",
"dirs 4.0.0",
"futures",
"lazy_static",
@@ -6215,6 +6215,7 @@ dependencies = [
"async-trait",
"base64 0.21.4",
"cfg-if",
"clap 4.4.7",
"dashmap",
"dirs 4.0.0",
"futures",
@@ -6523,7 +6524,7 @@ dependencies = [
"atty",
"bip39",
"bs58 0.4.0",
"clap 4.4.6",
"clap 4.4.7",
"colored",
"dashmap",
"dirs 4.0.0",
@@ -6700,7 +6701,7 @@ dependencies = [
"axum",
"bs58 0.4.0",
"cfg-if",
"clap 4.4.6",
"clap 4.4.7",
"colored",
"cpu-cycles",
"cupid",
@@ -6820,7 +6821,7 @@ dependencies = [
"async-file-watcher",
"async-trait",
"bs58 0.4.0",
"clap 4.4.6",
"clap 4.4.7",
"dirs 4.0.0",
"futures",
"humantime-serde",
@@ -6982,7 +6983,7 @@ name = "nym-nr-query"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 4.4.6",
"clap 4.4.7",
"log",
"nym-bin-common",
"nym-network-defaults",
@@ -7107,7 +7108,7 @@ dependencies = [
name = "nym-socks5-client"
version = "1.1.30"
dependencies = [
"clap 4.4.6",
"clap 4.4.7",
"lazy_static",
"log",
"nym-bin-common",
@@ -9534,7 +9535,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"cargo-edit",
"clap 4.4.6",
"clap 4.4.7",
"semver 1.0.20",
"serde",
"serde_json",
@@ -10296,7 +10297,7 @@ name = "ssl-inject"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 4.4.6",
"clap 4.4.7",
"hex",
"tokio",
]
+1
View File
@@ -138,6 +138,7 @@ axum = "0.6.20"
base64 = "0.21.4"
bip39 = { version = "2.0.0", features = ["zeroize"] }
boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" }
clap = "4.4.7"
cfg-if = "1.0.0"
cosmwasm-derive = "=1.3.0"
cosmwasm-schema = "=1.3.0"
+2 -2
View File
@@ -20,7 +20,7 @@ futures = { workspace = true } # bunch of futures stuff, however, now that I thi
# and the single instance of abortable we have should really be refactored anyway
url = { workspace = true }
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive"] }
dirs = "4.0"
lazy_static = "1.4.0"
log = { workspace = true } # self explanatory
@@ -36,7 +36,7 @@ tokio-tungstenite = { workspace = true }
## internal
nym-bandwidth-controller = { path = "../../common/bandwidth-controller" }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] }
nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
+20
View File
@@ -16,8 +16,10 @@ use std::net::{IpAddr, Ipv4Addr};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use nym_client_core::config::disk_persistence::CommonClientPaths;
pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig};
use nym_client_core::init::client_init::ClientConfig;
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_20;
@@ -72,6 +74,24 @@ impl NymConfigTemplate for Config {
}
}
impl ClientConfig for Config {
fn common_paths(&self) -> &CommonClientPaths {
&self.storage_paths.common_paths
}
fn core_config(&self) -> &BaseClientConfig {
&self.base
}
fn default_store_location(&self) -> PathBuf {
self.default_location()
}
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
save_formatted_config_to_file(self, path)
}
}
impl Config {
pub fn new<S: AsRef<str>>(id: S) -> Self {
Config {
+53 -149
View File
@@ -12,55 +12,49 @@ use crate::{
};
use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup};
use nym_crypto::asymmetric::identity;
use nym_sphinx::addressing::clients::Recipient;
use nym_topology::NymTopology;
use nym_client_core::init::client_init::{
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
};
use serde::Serialize;
use std::fmt::Display;
use std::fs;
use std::net::IpAddr;
use std::path::PathBuf;
use std::{fs, io};
use tap::TapFallible;
struct NativeClientInit;
impl InitialisableClient for NativeClientInit {
const NAME: &'static str = "native";
type Error = ClientError;
type InitArgs = Init;
type Config = Config;
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
try_upgrade_config(id)
}
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))?;
Ok(())
}
fn default_config_path(id: &str) -> PathBuf {
default_config_filepath(id)
}
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
override_config(
Config::new(&init_args.common_args.id),
OverrideConfig::from(init_args.clone()),
)
}
}
#[derive(Args, Clone)]
pub(crate) struct Init {
/// Id of the nym-mixnet-client we want to create config for.
#[clap(long)]
id: String,
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<identity::PublicKey>,
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
/// uniformly.
#[clap(long, conflicts_with = "gateway")]
latency_based_selection: bool,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
#[clap(long)]
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[clap(
long,
alias = "api_validators",
value_delimiter = ',',
group = "network"
)]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
#[command(flatten)]
common_args: CommonClientInitArgs,
/// Whether to not start the websocket
#[clap(long)]
@@ -74,10 +68,6 @@ pub(crate) struct Init {
#[clap(long)]
host: Option<IpAddr>,
/// Path to .json file containing custom network specification.
#[clap(long, group = "network", hide = true)]
custom_mixnet: Option<PathBuf>,
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
@@ -87,27 +77,28 @@ pub(crate) struct Init {
#[clap(long, hide = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
impl AsRef<CommonClientInitArgs> for Init {
fn as_ref(&self) -> &CommonClientInitArgs {
&self.common_args
}
}
impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self {
OverrideConfig {
nym_apis: init_config.nym_apis,
nym_apis: init_config.common_args.nym_apis,
disable_socket: init_config.disable_socket,
port: init_config.port,
host: init_config.host,
fastmode: init_config.fastmode,
no_cover: init_config.no_cover,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
nyxd_urls: init_config.common_args.nyxd_urls,
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
}
}
}
@@ -121,15 +112,11 @@ pub struct InitResults {
}
impl InitResults {
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
fn new(res: InitResultsWithConfig<Config>) -> Self {
Self {
client_core: nym_client_core::init::types::InitResults::new(
&config.base,
address,
gateway,
),
client_listening_port: config.socket.listening_port,
client_address: address.to_string(),
client_address: res.init_results.address.to_string(),
client_core: res.init_results,
client_listening_port: res.config.socket.listening_port,
}
}
}
@@ -142,97 +129,14 @@ impl Display for InitResults {
}
}
fn init_paths(id: &str) -> io::Result<()> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))
}
pub(crate) async fn execute(args: Init) -> Result<(), ClientError> {
eprintln!("Initialising client...");
let id = &args.id;
let output = args.output;
let res = initialise_client::<NativeClientInit>(args).await?;
let already_init = if default_config_filepath(id).exists() {
// in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op)
try_upgrade_config(id)?;
eprintln!("Client \"{id}\" was already initialised before");
true
} else {
init_paths(id)?;
false
};
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
eprintln!("Instructed to force registering gateway. This will overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
// Unless the user really wants to.
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let selection_spec = GatewaySelectionSpecification::new(
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(args.latency_based_selection),
false,
);
// Load and potentially override config
let config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let available_gateways = if let Some(hardcoded_topology) = args
.custom_mixnet
.map(NymTopology::new_from_file)
.transpose()?
{
// hardcoded_topology
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
current_gateways(&mut rng, &config.base.client.nym_api_urls).await?
};
let gateway_setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
overwrite_data: register_gateway,
};
let init_details =
nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store)
.await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
log::error!("Failed to save the config file");
})?;
eprintln!(
"Saved configuration file to {}",
config_save_location.display()
);
let address = init_details.client_address()?;
eprintln!("Client configuration completed.\n");
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
};
let init_results = InitResults::new(&config, &address, &gateway_details);
println!("{}", args.output.format(&init_results));
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
Ok(())
}
+2 -2
View File
@@ -7,7 +7,7 @@ edition = "2021"
rust-version = "1.56"
[dependencies]
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive"] }
lazy_static = "1.4.0"
log = { workspace = true }
pretty_env_logger = "0.4"
@@ -21,7 +21,7 @@ url = { workspace = true }
# internal
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage"] }
nym-client-core = { path = "../../common/client-core", features = ["fs-surb-storage", "cli"] }
nym-coconut-interface = { path = "../../common/coconut-interface" }
nym-config = { path = "../../common/config" }
nym-credentials = { path = "../../common/credentials" }
+53 -152
View File
@@ -11,27 +11,50 @@ use crate::{
};
use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup};
use nym_crypto::asymmetric::identity;
use nym_client_core::init::client_init::{
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
};
use nym_sphinx::addressing::clients::Recipient;
use nym_topology::NymTopology;
use serde::Serialize;
use std::fmt::Display;
use std::fs;
use std::net::{IpAddr, SocketAddr};
use std::path::PathBuf;
use std::{fs, io};
use tap::TapFallible;
struct Socks5ClientInit;
impl InitialisableClient for Socks5ClientInit {
const NAME: &'static str = "socks5";
type Error = Socks5ClientError;
type InitArgs = Init;
type Config = Config;
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
try_upgrade_config(id)
}
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))?;
Ok(())
}
fn default_config_path(id: &str) -> PathBuf {
default_config_filepath(id)
}
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
override_config(
Config::new(&init_args.common_args.id, &init_args.provider.to_string()),
OverrideConfig::from(init_args.clone()),
)
}
}
#[derive(Args, Clone)]
pub(crate) struct Init {
/// Id of the nym-mixnet-client we want to create config for.
#[clap(long)]
id: String,
#[command(flatten)]
common_args: CommonClientInitArgs,
/// Address of the socks5 provider to send messages to.
#[clap(long)]
@@ -46,34 +69,6 @@ pub(crate) struct Init {
#[clap(long, alias = "use_anonymous_sender_tag")]
use_reply_surbs: Option<bool>,
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<identity::PublicKey>,
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
/// uniformly.
#[clap(long, conflicts_with = "gateway")]
latency_based_selection: bool,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
#[clap(long)]
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[clap(
long,
alias = "api_validators",
value_delimiter = ',',
group = "network"
)]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
/// Port for the socket to listen on in all subsequent runs
#[clap(short, long)]
port: Option<u16>,
@@ -82,10 +77,6 @@ pub(crate) struct Init {
#[clap(long)]
host: Option<IpAddr>,
/// Path to .json file containing custom network specification.
#[clap(long, group = "network", hide = true)]
custom_mixnet: Option<PathBuf>,
/// Mostly debug-related option to increase default traffic rate so that you would not need to
/// modify config post init
#[clap(long, hide = true)]
@@ -95,19 +86,20 @@ pub(crate) struct Init {
#[clap(long, hide = true)]
no_cover: bool,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[clap(long, hide = true)]
enabled_credentials_mode: Option<bool>,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
impl AsRef<CommonClientInitArgs> for Init {
fn as_ref(&self) -> &CommonClientInitArgs {
&self.common_args
}
}
impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self {
OverrideConfig {
nym_apis: init_config.nym_apis,
nym_apis: init_config.common_args.nym_apis,
ip: init_config.host,
port: init_config.port,
use_anonymous_replies: init_config.use_reply_surbs,
@@ -115,8 +107,8 @@ impl From<Init> for OverrideConfig {
no_cover: init_config.no_cover,
geo_routing: None,
medium_toggle: false,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
nyxd_urls: init_config.common_args.nyxd_urls,
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
outfox: false,
}
}
@@ -131,15 +123,11 @@ pub struct InitResults {
}
impl InitResults {
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
fn new(res: InitResultsWithConfig<Config>) -> Self {
Self {
client_core: nym_client_core::init::types::InitResults::new(
&config.core.base,
address,
gateway,
),
socks5_listening_address: config.core.socks5.bind_adddress,
client_address: address.to_string(),
client_address: res.init_results.address.to_string(),
client_core: res.init_results,
socks5_listening_address: res.config.core.socks5.bind_adddress,
}
}
}
@@ -156,101 +144,14 @@ impl Display for InitResults {
}
}
fn init_paths(id: &str) -> io::Result<()> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))
}
pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> {
eprintln!("Initialising client...");
let id = &args.id;
let provider_address = &args.provider;
let output = args.output;
let res = initialise_client::<Socks5ClientInit>(args).await?;
let already_init = if default_config_filepath(id).exists() {
// in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op)
try_upgrade_config(id)?;
eprintln!("SOCKS5 client \"{id}\" was already initialised before");
true
} else {
init_paths(id)?;
false
};
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
eprintln!("Instructed to force registering gateway. This might overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
// Unless the user really wants to.
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let selection_spec = GatewaySelectionSpecification::new(
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(args.latency_based_selection),
false,
);
// Load and potentially override config
let config = override_config(
Config::new(id, &provider_address.to_string()),
OverrideConfig::from(args.clone()),
);
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let available_gateways = if let Some(hardcoded_topology) = args
.custom_mixnet
.map(NymTopology::new_from_file)
.transpose()?
{
// hardcoded_topology
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
current_gateways(&mut rng, &config.core.base.client.nym_api_urls).await?
};
let gateway_setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
overwrite_data: register_gateway,
};
let init_details =
nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store)
.await
.tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?;
// TODO: ask the service provider we specified for its interface version and set it in the config
let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
log::error!("Failed to save the config file");
})?;
eprintln!(
"Saved configuration file to {}",
config_save_location.display()
);
let address = init_details.client_address()?;
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
};
let init_results = InitResults::new(&config, &address, &gateway_details);
println!("{}", args.output.format(&init_results));
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
Ok(())
}
+20
View File
@@ -15,7 +15,9 @@ use std::path::{Path, PathBuf};
use std::str::FromStr;
pub use crate::config::persistence::SocksClientPaths;
use nym_client_core::config::disk_persistence::CommonClientPaths;
pub use nym_client_core::config::Config as BaseClientConfig;
use nym_client_core::init::client_init::ClientConfig;
pub use nym_socks5_client_core::config::Config as CoreConfig;
pub mod old_config_v1_1_13;
@@ -69,6 +71,24 @@ impl NymConfigTemplate for Config {
}
}
impl ClientConfig for Config {
fn common_paths(&self) -> &CommonClientPaths {
&self.storage_paths.common_paths
}
fn core_config(&self) -> &BaseClientConfig {
&self.core.base
}
fn default_store_location(&self) -> PathBuf {
self.default_location()
}
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
save_formatted_config_to_file(self, path)
}
}
impl Config {
pub fn new<S: AsRef<str>>(id: S, provider_mix_address: S) -> Self {
Config {
+1 -1
View File
@@ -9,7 +9,7 @@ repository = { workspace = true }
[dependencies]
atty = "0.2"
clap = { version = "4.0", features = ["derive"] }
clap = { workspace = true, features = ["derive"] }
clap_complete = "4.0"
clap_complete_fig = "4.0"
log = { workspace = true }
+2
View File
@@ -11,6 +11,7 @@ rust-version = "1.66"
async-trait = { workspace = true }
base64 = "0.21.2"
cfg-if = "1.0.0"
clap = { workspace = true, optional = true }
dashmap = { workspace = true }
dirs = "4.0"
futures = { workspace = true }
@@ -92,6 +93,7 @@ sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "sqlite", "macro
[features]
default = []
cli = ["clap"]
fs-surb-storage = ["sqlx"]
wasm = ["nym-gateway-client/wasm"]
+21
View File
@@ -8,6 +8,7 @@ use nym_topology::gateway::GatewayConversionError;
use nym_topology::NymTopologyError;
use nym_validator_client::ValidatorClientError;
use std::error::Error;
use std::path::PathBuf;
#[derive(thiserror::Error, Debug)]
pub enum ClientCoreError {
@@ -132,6 +133,26 @@ pub enum ClientCoreError {
#[error("the specified gateway '{gateway}' does not support the wss protocol")]
UnsupportedWssProtocol { gateway: String },
#[error(
"failed to load custom topology using path '{}'. detailed message: {source}", file_path.display()
)]
CustomTopologyLoadFailure {
file_path: PathBuf,
#[source]
source: std::io::Error,
},
#[error(
"failed to save config file for client-{typ} id {id} using path '{}'. detailed message: {source}", path.display()
)]
ConfigSaveFailure {
typ: String,
id: String,
path: PathBuf,
#[source]
source: std::io::Error,
},
}
/// Set of messages that the client can send to listeners via the task manager
+201
View File
@@ -0,0 +1,201 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::disk_persistence::CommonClientPaths;
use crate::error::ClientCoreError;
use crate::{
client::{
base_client::storage::gateway_details::OnDiskGatewayDetails,
key_manager::persistence::OnDiskKeys,
},
init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup, InitResults},
};
use log::info;
use nym_crypto::asymmetric::identity;
use nym_topology::NymTopology;
use std::path::{Path, PathBuf};
pub trait InitialisableClient {
const NAME: &'static str;
type Error: From<ClientCoreError>;
type InitArgs: AsRef<CommonClientInitArgs>;
type Config: ClientConfig;
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error>;
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error>;
fn default_config_path(id: &str) -> PathBuf;
fn construct_config(init_args: &Self::InitArgs) -> Self::Config;
}
pub trait ClientConfig {
fn common_paths(&self) -> &CommonClientPaths;
fn core_config(&self) -> &crate::config::Config;
fn default_store_location(&self) -> PathBuf;
fn save_to<P: AsRef<Path>>(&self, path: P) -> std::io::Result<()>;
}
#[cfg_attr(feature = "cli", derive(clap::Args))]
#[derive(Debug, Clone)]
pub struct CommonClientInitArgs {
/// Id of client we want to create config for.
#[cfg_attr(feature = "cli", clap(long))]
pub id: String,
/// Id of the gateway we are going to connect to.
#[cfg_attr(feature = "cli", clap(long))]
pub gateway: Option<identity::PublicKey>,
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
/// uniformly.
#[cfg_attr(feature = "cli", clap(long, conflicts_with = "gateway"))]
pub latency_based_selection: bool,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
#[cfg_attr(feature = "cli", clap(long))]
pub force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[cfg_attr(
feature = "cli",
clap(long, alias = "nyxd_validators", value_delimiter = ',', hide = true)
)]
pub nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[cfg_attr(
feature = "cli",
clap(
long,
alias = "api_validators",
value_delimiter = ',',
group = "network"
)
)]
pub nym_apis: Option<Vec<url::Url>>,
/// Path to .json file containing custom network specification.
#[cfg_attr(feature = "cli", clap(long, group = "network", hide = true))]
pub custom_mixnet: Option<PathBuf>,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[cfg_attr(feature = "cli", clap(long, hide = true))]
pub enabled_credentials_mode: Option<bool>,
}
pub struct InitResultsWithConfig<T> {
pub config: T,
pub init_results: InitResults,
}
pub async fn initialise_client<C>(
init_args: C::InitArgs,
) -> Result<InitResultsWithConfig<C::Config>, C::Error>
where
C: InitialisableClient,
{
info!("initialising {} client", C::NAME);
let common_args = init_args.as_ref();
let id = &common_args.id;
let already_init = if C::default_config_path(id).exists() {
// in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op)
C::try_upgrade_outdated_config(id)?;
eprintln!("{} client \"{id}\" was already initialised before", C::NAME);
true
} else {
C::initialise_storage_paths(id)?;
false
};
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = common_args.force_register_gateway;
if user_wants_force_register {
eprintln!("Instructed to force registering gateway. This might overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
// Unless the user really wants to.
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = common_args.gateway;
let selection_spec = GatewaySelectionSpecification::new(
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(common_args.latency_based_selection),
false,
);
// Load and potentially override config
let config = C::construct_config(&init_args);
let paths = config.common_paths();
let core = config.core_config();
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::new(paths.keys.clone());
let details_store = OnDiskGatewayDetails::new(&paths.gateway_details);
let available_gateways = if let Some(custom_mixnet) = common_args.custom_mixnet.as_ref() {
let hardcoded_topology = NymTopology::new_from_file(custom_mixnet).map_err(|source| {
ClientCoreError::CustomTopologyLoadFailure {
file_path: custom_mixnet.clone(),
source,
}
})?;
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
crate::init::helpers::current_gateways(&mut rng, &core.client.nym_api_urls).await?
};
let gateway_setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
overwrite_data: register_gateway,
};
let init_details =
crate::init::setup_gateway(gateway_setup, &key_store, &details_store).await?;
// TODO: ask the service provider we specified for its interface version and set it in the config
let config_save_location = config.default_store_location();
if let Err(err) = config.save_to(&config_save_location) {
return Err(ClientCoreError::ConfigSaveFailure {
typ: C::NAME.to_string(),
id: id.to_string(),
path: config_save_location,
source: err,
}
.into());
}
eprintln!(
"Saved configuration file to {}",
config_save_location.display()
);
let address = init_details.client_address()?;
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
};
let init_results = InitResults::new(config.core_config(), address, &gateway_details);
Ok(InitResultsWithConfig {
config,
init_results,
})
}
+1
View File
@@ -24,6 +24,7 @@ use serde::de::DeserializeOwned;
use serde::Serialize;
use std::sync::Arc;
pub mod client_init;
pub mod helpers;
pub mod types;
+9 -7
View File
@@ -296,16 +296,17 @@ impl<T> GatewaySetup<T> {
/// Struct describing the results of the client initialization procedure.
#[derive(Debug, Serialize)]
pub struct InitResults {
version: String,
id: String,
identity_key: String,
encryption_key: String,
gateway_id: String,
gateway_listener: String,
pub version: String,
pub id: String,
pub identity_key: String,
pub encryption_key: String,
pub gateway_id: String,
pub gateway_listener: String,
pub address: Recipient,
}
impl InitResults {
pub fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
pub fn new(config: &Config, address: Recipient, gateway: &GatewayEndpointConfig) -> Self {
Self {
version: config.client.version.clone(),
id: config.client.id.clone(),
@@ -313,6 +314,7 @@ impl InitResults {
encryption_key: address.encryption_key().to_base58_string(),
gateway_id: gateway.gateway_id.clone(),
gateway_listener: gateway.gateway_listener.clone(),
address,
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ bip39 = { workspace = true }
bs58 = "0.4"
comfy-table = "6.0.0"
cfg-if = "1.0.0"
clap = { version = "4.0", features = ["derive"] }
clap = { workspace = true, features = ["derive"] }
cw-utils = { workspace = true }
handlebars = "3.0.1"
humantime-serde = "1.0"
+1 -1
View File
@@ -21,7 +21,7 @@ bs58 = "0.4.0"
bytes = "1.3.0"
cfg-if = "1.0.0"
chrono = { version = "0.4.24", default-features = false, features = ["clock"] }
clap = { version = "4.0.32", features = ["derive"] }
clap = { workspace = true, features = ["derive"] }
config = { version = "0.13", default-features = false, features = ["toml"] }
digest = "0.10.6"
dirs = "5.0.0"
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
chrono = { version = "0.4.31", features = ["serde"] }
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive"] }
dotenvy = "0.15.6"
humantime-serde = "1.0"
isocountry = "0.3.2"
+1 -1
View File
@@ -20,7 +20,7 @@ async-trait = { workspace = true }
atty = "0.2"
bip39 = { workspace = true }
bs58 = "0.4.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive"] }
colored = "2.0"
dashmap = { workspace = true }
dirs = "4.0"
+1 -1
View File
@@ -19,7 +19,7 @@ rust-version = "1.58.1"
axum = { workspace = true }
anyhow = "1.0.40"
bs58 = "0.4.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive"] }
colored = "2.0"
cupid = "0.6.1"
dirs = "4.0"
+1 -1
View File
@@ -19,7 +19,7 @@ async-trait = { workspace = true }
bs58 = { version = "0.4.0" }
bip39 = { workspace = true }
cfg-if = "1.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive"] }
console-subscriber = { version = "0.1.1", optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable"
dirs = "4.0"
futures = { workspace = true }
+12 -14
View File
@@ -126,16 +126,15 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.3.2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
@@ -165,9 +164,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
version = "1.0.2"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
@@ -868,20 +867,19 @@ dependencies = [
[[package]]
name = "clap"
version = "4.3.21"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
dependencies = [
"clap_builder",
"clap_derive",
"once_cell",
]
[[package]]
name = "clap_builder"
version = "4.3.21"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
dependencies = [
"anstream",
"anstyle",
@@ -910,9 +908,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.3.12"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@@ -922,9 +920,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "cocoa"
+22 -14
View File
@@ -108,16 +108,15 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.3.2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
@@ -147,9 +146,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
version = "1.0.2"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
@@ -662,20 +661,19 @@ dependencies = [
[[package]]
name = "clap"
version = "4.3.21"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
dependencies = [
"clap_builder",
"clap_derive",
"once_cell",
]
[[package]]
name = "clap_builder"
version = "4.3.21"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
dependencies = [
"anstream",
"anstyle",
@@ -704,9 +702,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.3.12"
version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@@ -716,9 +714,9 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "cocoa"
@@ -3431,6 +3429,15 @@ dependencies = [
"nym-contracts-common",
]
[[package]]
name = "nym-exit-policy"
version = "0.1.0"
dependencies = [
"serde",
"thiserror",
"tracing",
]
[[package]]
name = "nym-group-contract-common"
version = "0.1.0"
@@ -3510,6 +3517,7 @@ dependencies = [
"base64 0.21.4",
"nym-bin-common",
"nym-crypto",
"nym-exit-policy",
"nym-wireguard-types",
"schemars",
"serde",
@@ -17,7 +17,7 @@ path = "src/lib.rs"
[dependencies]
async-trait = { workspace = true }
bs58 = "0.4.0"
clap = {version = "4.0", features = ["cargo", "derive"]}
clap = { workspace = true, features = ["cargo", "derive"]}
dirs = "4.0"
futures = { workspace = true }
humantime-serde = "1.1.1"
@@ -41,7 +41,7 @@ url = { workspace = true }
# internal
async-file-watcher = { path = "../../common/async-file-watcher" }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-client-core = { path = "../../common/client-core" }
nym-client-core = { path = "../../common/client-core", features = ["cli"] }
nym-client-websocket-requests = { path = "../../clients/native/websocket-requests" }
nym-config = { path = "../../common/config" }
nym-credential-storage = { path = "../../common/credential-storage" }
@@ -10,27 +10,48 @@ use crate::{
};
use clap::Args;
use nym_bin_common::output_format::OutputFormat;
use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails;
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
use nym_client_core::config::GatewayEndpointConfig;
use nym_client_core::error::ClientCoreError;
use nym_client_core::init::helpers::current_gateways;
use nym_client_core::init::types::GatewaySetup;
use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification};
use nym_crypto::asymmetric::identity;
use nym_sdk::mixnet::NymTopology;
use nym_sphinx::addressing::clients::Recipient;
use nym_client_core::init::client_init::{
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
};
use serde::Serialize;
use std::fmt::Display;
use std::fs;
use std::path::PathBuf;
use std::{fs, io};
use tap::TapFallible;
struct NetworkRequesterInit;
impl InitialisableClient for NetworkRequesterInit {
const NAME: &'static str = "network requester";
type Error = NetworkRequesterError;
type InitArgs = Init;
type Config = Config;
fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
try_upgrade_config(id)
}
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))?;
Ok(())
}
fn default_config_path(id: &str) -> PathBuf {
default_config_filepath(id)
}
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
override_config(
Config::new(&init_args.common_args.id),
OverrideConfig::from(init_args.clone()),
)
}
}
#[derive(Args, Clone)]
pub(crate) struct Init {
/// Id of the nym-mixnet-client we want to create config for.
#[clap(long)]
id: String,
#[command(flatten)]
common_args: CommonClientInitArgs,
/// Specifies whether this network requester should run in 'open-proxy' mode
#[clap(long)]
@@ -45,43 +66,6 @@ pub(crate) struct Init {
#[clap(long)]
statistics_recipient: Option<String>,
/// Id of the gateway we are going to connect to.
#[clap(long)]
gateway: Option<identity::PublicKey>,
/// Specifies whether the new gateway should be determined based by latency as opposed to being chosen
/// uniformly.
#[clap(long, conflicts_with = "gateway")]
latency_based_selection: bool,
/// Force register gateway. WARNING: this will overwrite any existing keys for the given id,
/// potentially causing loss of access.
#[clap(long)]
force_register_gateway: bool,
/// Comma separated list of rest endpoints of the nyxd validators
#[clap(long, alias = "nymd_validators", value_delimiter = ',')]
nyxd_urls: Option<Vec<url::Url>>,
/// Comma separated list of rest endpoints of the API validators
#[clap(
long,
alias = "api_validators",
value_delimiter = ',',
group = "network"
)]
// the alias here is included for backwards compatibility (1.1.4 and before)
nym_apis: Option<Vec<url::Url>>,
/// Path to .json file containing custom network specification.
#[clap(long, group = "network", hide = true)]
custom_mixnet: Option<PathBuf>,
/// Set this client to work in a enabled credentials mode that would attempt to use gateway
/// with bandwidth credential requirement.
#[clap(long)]
enabled_credentials_mode: Option<bool>,
/// Specifies whether this network requester will run using the default ExitPolicy
/// as opposed to the allow list.
/// Note: this setting will become the default in the future releases.
@@ -95,20 +79,26 @@ pub(crate) struct Init {
impl From<Init> for OverrideConfig {
fn from(init_config: Init) -> Self {
OverrideConfig {
nym_apis: init_config.nym_apis,
nym_apis: init_config.common_args.nym_apis,
fastmode: false,
no_cover: false,
medium_toggle: false,
nyxd_urls: init_config.nyxd_urls,
enabled_credentials_mode: init_config.enabled_credentials_mode,
nyxd_urls: init_config.common_args.nyxd_urls,
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
enable_exit_policy: init_config.with_exit_policy,
open_proxy: init_config.open_proxy,
enable_statistics: init_config.enabled_credentials_mode,
enable_statistics: init_config.enable_statistics,
statistics_recipient: init_config.statistics_recipient,
}
}
}
impl AsRef<CommonClientInitArgs> for Init {
fn as_ref(&self) -> &CommonClientInitArgs {
&self.common_args
}
}
#[derive(Debug, Serialize)]
pub struct InitResults {
#[serde(flatten)]
@@ -117,14 +107,10 @@ pub struct InitResults {
}
impl InitResults {
fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self {
fn new(res: InitResultsWithConfig<Config>) -> Self {
Self {
client_core: nym_client_core::init::types::InitResults::new(
&config.base,
address,
gateway,
),
client_address: address.to_string(),
client_address: res.init_results.address.to_string(),
client_core: res.init_results,
}
}
}
@@ -140,99 +126,14 @@ impl Display for InitResults {
}
}
fn init_paths(id: &str) -> io::Result<()> {
fs::create_dir_all(default_data_directory(id))?;
fs::create_dir_all(default_config_directory(id))
}
pub(crate) async fn execute(args: Init) -> Result<(), NetworkRequesterError> {
eprintln!("Initialising client...");
pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> {
log::info!("Initialising client...");
let output = args.output;
let res = initialise_client::<NetworkRequesterInit>(args).await?;
let id = &args.id;
let already_init = if default_config_filepath(id).exists() {
// in case we're using old config, try to upgrade it
// (if we're using the current version, it's a no-op)
try_upgrade_config(id)?;
log::info!("Client \"{id}\" was already initialised before");
true
} else {
init_paths(&args.id)?;
false
};
// Usually you only register with the gateway on the first init, however you can force
// re-registering if wanted.
let user_wants_force_register = args.force_register_gateway;
if user_wants_force_register {
log::warn!("Instructed to force registering gateway. This might overwrite keys!");
}
// If the client was already initialized, don't generate new keys and don't re-register with
// the gateway (because this would create a new shared key).
// Unless the user really wants to.
let register_gateway = !already_init || user_wants_force_register;
// Attempt to use a user-provided gateway, if possible
let user_chosen_gateway_id = args.gateway;
let selection_spec = GatewaySelectionSpecification::new(
user_chosen_gateway_id.map(|id| id.to_base58_string()),
Some(args.latency_based_selection),
false,
);
// Load and potentially override config
let config = override_config(Config::new(id), OverrideConfig::from(args.clone()));
log::debug!("Using config: {:#?}", config);
// Setup gateway by either registering a new one, or creating a new config from the selected
// one but with keys kept, or reusing the gateway configuration.
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
let details_store =
OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details);
let available_gateways = if let Some(hardcoded_topology) = args
.custom_mixnet
.as_ref()
.map(NymTopology::new_from_file)
.transpose()?
{
// hardcoded_topology
hardcoded_topology.get_gateways()
} else {
let mut rng = rand::thread_rng();
current_gateways(&mut rng, &config.base.client.nym_api_urls).await?
};
let gateway_setup = GatewaySetup::New {
specification: selection_spec,
available_gateways,
overwrite_data: register_gateway,
};
let init_details =
nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store)
.await
.tap_err(|err| log::error!("Failed to setup gateway\nError: {err}"))?;
let config_save_location = config.default_location();
config.save_to_default_location().tap_err(|_| {
log::error!("Failed to save the config file");
})?;
log::info!(
"Saved configuration file to {}",
config_save_location.display()
);
let address = init_details.client_address()?;
log::info!("Client configuration completed.\n");
let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else {
return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?;
};
let init_results = InitResults::new(&config, &address, &gateway_details);
println!("{}", args.output.format(&init_results));
let init_results = InitResults::new(res);
println!("{}", output.format(&init_results));
Ok(())
}
@@ -154,7 +154,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> {
let bin_name = "nym-network-requester";
match args.command {
Commands::Init(m) => init::execute(&m).await?,
Commands::Init(m) => init::execute(m).await?,
Commands::Run(m) => run::execute(&m).await?,
Commands::Sign(m) => sign::execute(&m).await?,
Commands::BuildInfo(m) => build_info::execute(m),
@@ -17,8 +17,10 @@ use std::str::FromStr;
use std::time::Duration;
use url::Url;
use nym_client_core::config::disk_persistence::CommonClientPaths;
pub use nym_client_core::config::Config as BaseClientConfig;
pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig};
use nym_client_core::init::client_init::ClientConfig;
use nym_network_defaults::mainnet;
use nym_sphinx::params::PacketSize;
@@ -83,6 +85,24 @@ impl NymConfigTemplate for Config {
}
}
impl ClientConfig for Config {
fn common_paths(&self) -> &CommonClientPaths {
&self.storage_paths.common_paths
}
fn core_config(&self) -> &BaseClientConfig {
&self.base
}
fn default_store_location(&self) -> PathBuf {
self.default_location()
}
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
save_formatted_config_to_file(self, path)
}
}
impl Config {
pub fn new<S: AsRef<str>>(id: S) -> Self {
Config {
+1 -1
View File
@@ -13,7 +13,7 @@ license.workspace = true
[dependencies]
anyhow = { workspace = true }
cargo-edit = "0.11.0"
clap = { version = "4.3.19", features = ["derive", "string"] }
clap = { workspace = true, features = ["derive", "string"] }
semver = "1.0.18"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
base64 = "0.13.0"
bs58 = "0.4"
clap = { version = "4.0", features = ["derive"] }
clap = { workspace = true, features = ["derive"] }
clap_complete = "4.0"
clap_complete_fig = "4.0"
dotenvy = "0.15.6"
+1 -1
View File
@@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
anyhow = { workspace = true }
clap = {version = "4.0", features = ["cargo", "derive"]}
clap = { workspace = true, features = ["cargo", "derive"]}
log = { workspace = true }
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
nym-network-defaults = { path = "../../common/network-defaults" }